Docker部署Scrapy-redis分散式爬蟲框架(整合Selenium+Headless Chrome網頁渲染)
前言
我的京東價格監控網站需要不間斷爬取京東商品頁面,爬蟲模組我採用了Scrapy+selenium+Headless Chrome的方式進行商品資訊的採集。
由於最近爬蟲用的伺服器到期,需要換到新伺服器重新部署,所以乾脆把整個模組封裝入Docker,以便後續能夠方便快速的進行爬蟲的部署。同時,由於我的Scrapy整合了redis,能夠支援分散式爬取,Docker化後也更方便進行分散式的拓展。
任務需求
- 將爬蟲程式碼打包為Docker映象
- 在全新的伺服器上安裝Docker
- 使用單獨的Redis容器作為爬取url佇列(也就是Scrapy-redis中redis的主要用處)
- 所有新開的爬蟲容器連線Redis容器
步驟
打包爬蟲程式碼
Scrapy內建的crawler不支援頁面渲染的方式進行頁面渲染,需要使用scrapy-splash或者selenium作為中介軟體,才能夠支援頁面渲染爬取。我在程式碼中整合了selenium,並在系統中安裝了chrome,這在docker中,需要在打包時將chrome安裝至映象中。
Dockerfile檔案中,將chrome下載並安裝至映象,並且將chromedriver放入系統,保證selenium程式碼能夠呼叫到chrome。
我參考了開源庫:https://github.com/joyzoursky/docker-python-chromedriver
最後完成的Dockerfile檔案:
FROM python:3.6 # install google chrome RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' RUN apt-get -y update RUN apt-get install -y google-chrome-stable # install chromedriver RUN apt-get install -yqq unzip RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/ # set display port to avoid crash ENV DISPLAY=:99 # copy pm_scrapy WORKDIR /usr/src/app COPY . . # install requirements RUN pip install -r requirements.txt CMD scrapy crawl JDcate
寫完Docker檔案,在打包前,最好還要加上.dockerignore避免吧沒用的檔案打包進映象。
我打包的程式碼結構圖如下:
使用命令,生成映象:
sudo docker image build -t pm_scrapy .
REPOSITORY TAG IMAGE ID CREATED SIZE
pm_scrapy latest 082e7e350831 47 hours ago 1.41 GB
proxy_pool latest 83a95913162b 6 days ago 1.01 GB
python 3.6 749d36d00e00 10 days ago 921 MB
redis latest 5d2989ac9711 10 days ago 95 MB
1.41G,大的嚇人。
執行redis容器
映象打包好之後,別急著執行,因為新伺服器上,Redis還沒有呢。
原則上來說,你可以使用docker-compose,把redis和爬蟲程式碼兩個映象同時執行起來。
我這裡,我將redis開啟單獨的映象,一是為了方便其它模組使用redis,二是方便以後開更多的scrapy進行分散式爬取。
使用官方的redis映象開啟redis容器,並將redis埠對映到宿主機6379:
docker run -p 6379:6379 -d redis --requirepass "密碼"
官方的redis設定中預設就是0.0.0.0,不用擔心宿主機無法訪問。
連線爬蟲容器和redis容器
接下來可以執行爬蟲容器,需要注意的是,連線兩個容器,需要使用link。
首先找到redis容器的ID,或者你給他自定義的名字
接著執行並連線容器:
sudo docker container run -itd --link 00c2655515fb:redis pm_scrapy
出現問題:Docker 使用--link出現Cannot link to /xxx, as it does not belong to xxxxx異常
這個異常的原因是redis在一個特殊的網路裡,你需要用:
docker inspect [需要link的容器名稱或ID]
來檢視redis容器所在的網段。
同時還可以看看
docker network ls
之後你就需要類似這樣的語句(多指定--net來定下容器所在網路):
docker run -d --name movie_project -p 9090:80 --link 容器名:別名 --net link_continer_network -v /root/project/movie_project:/app:Z python2/nginx/flask
參考:
https://blog.csdn.net/hanchaobiao/article/details/81911587
https://www.jianshu.com/p/21d66ca6115e
跑程式碼
一切就緒,發現爬蟲沒法執行,使用docker logs 容器ID
檢視log。發現問題
出現問題:headless chrome:DevToolsActivePort file doesn't exist while trying to initiate Chrome Browser
這個問題參考下面的網址,這裡直接給出解決方案,在你的程式碼里加一行引數:
chrome_options.add_argument('--disable-dev-shm-usage')
這是我的程式碼截圖:
參考:
對該容器的日常維護
平日裡可以使用docker exec -it 21323a52d19f /bin/bash
進入正在執行容器的bash,檢視下爬蟲狀態
關注我
本人目前為後臺開發工程師,主要關注Python爬蟲,後臺開發等相關技術。
原創部落格主要內容:
- 筆試面試複習知識點手冊
- Leetcode演算法題解析(前150題)
- 劍指offer演算法題解析
- Python爬蟲相關實戰
- 後臺開發相關實戰
同步更新以下幾大部落格:
- Csdn:
擁有專欄:Leetcode題解(Java/Python)、Python爬蟲開發
- 知乎:
https://www.zhihu.com/people/yang-zhen-dong-1/
擁有專欄:碼農面試助攻手冊
- 掘金:
https://juejin.im/user/2119514149109095
- 簡書:
https://www.jianshu.com/u/b5f225ca2376
- 個人公眾號:Rude3Knife