一.部署前的準備
在開始部署之前,先梳理一下幾個關鍵詞:
1.Scrapy
Scrapy是一個基於Twisted的異步處理框架,是純Python實現的爬蟲框架。Scrapy由Spider、Middleware、Downloader、Pipeline等組成,各個模塊之間耦合度低,擴展性強。Scrapy的整體結構如下:
2.Scrapyd
Scrapyd是一個用於部署和運行scrapy項目的工具,通過Scrapyd可以將已經寫好的Scrapy項目上傳到雲主機並通過scrapyd提供的Restful API來控制它們的運行。
3.Scrapyd-Client
在將Scrapy代碼部署到遠程Scrapyd的時候,第一步就是要將代碼打包爲EGG文件(EGG是二進制文件),其次需要將EGG文件上傳到雲主機。這個過程可以使用程序實現,也可以使用Scrapyd-Client來實現。
以圖2爲例子,客戶端做的有兩個操作:
- 通過Scrapyd-Client打包Scrapy項目併發送到對應的已經在運行Scrapyd進程的服務器上;
- 客戶端通過發送HTTP請求來獲取或者控制爬蟲的運行。
二.Scrapyd的Docker化
在把Scrapyd放入容器之前,首先要考慮需要什麼。
1.scrapyd的運行依賴庫
需要一個requirements.txt文件來安裝scrapyd的依賴文件,解決辦法是在本地開發scrapy的時候使用到python的虛擬環境,比如virtualenv,以便於版本控制和導出requirements.txt。
對於開發來說,環境配置一直就是個問題,最大的問題就是版本不一致。在Python中,可以使用virtualenv來解決上面的問題,但是virtualenv對於項目部署來說並不方便,而此時使用Docker則是更好的選擇。
項目鏈接:https://github.com/sky94520/ScrapyTutorial
上面的項目爲scrapy的一個簡例,它的任務就是爬取http://quotes.toscrape.com/網站的名言,並把這些數據存儲到mongodb中去。如果對mongodb不熟悉的可以改爲存在csv文件或者json文件中,只需要添加一個對應的pipeline即可。
上面的這個例子包含了兩個標籤(tag):mongodb和json。mongodb標籤將會把數據保存到mongodb中;而json標籤將會把數據保存到quotes.json文件中。
使用git clone https://github.com/sky94520/ScrapyTutorial.git 把項目從github中克隆下來;然後在控制檯中切換到對應的標籤,比如這裏要切換到json標籤,需要鍵入:
git checkout json
這裏使用的是windows環境下的cmd。在項目根目錄下,使用下面的命令進入到虛擬環境下:
venv\Scripts\activate
如果執行成功的話會出現下面這樣:
此時無論是執行python文件、還是安裝/卸載庫都是隻會影響這個虛擬環境。
接着就可以導出該環境下的依賴庫文件:
pip freeze > requirements.txt
requirements.txt文件顯示如下:
asn1crypto==0.24.0
attrs==19.1.0
Automat==0.7.0
cffi==1.12.3
constantly==15.1.0
cryptography==2.6.1
cssselect==1.0.3
hyperlink==19.0.0
idna==2.8
incremental==17.5.0
lxml==4.3.3
parsel==1.5.1
pyasn1==0.4.5
pyasn1-modules==0.2.5
pycparser==2.19
PyDispatcher==2.0.5
PyHamcrest==1.9.0
pymongo==3.8.0
pyOpenSSL==19.0.0
pywin32==224
queuelib==1.5.0
Scrapy==1.6.0
service-identity==18.1.0
six==1.12.0
Twisted==18.9.0
w3lib==1.20.0
zope.interface==4.6.0
注:Twisted的版本爲18.9.0,scrapy的版本爲scrapy==1.6.0,否則scrapyd的網頁訪問將會出錯。 另外,在虛擬環境下輸入deactivate表示退出虛擬環境。
2.外網可以訪問Scrapyd
可以參考官方網站https://scrapyd.readthedocs.io/en/latest/config.html,要了解的主要包括配置文件和配置文件的路徑;由於這裏使用的是ubuntu,所以配置文件放在/etc/scrapyd/目錄下,配置文件scrapyd.conf內容如下:
[scrapyd]
eggs_dir = eggs
logs_dir = logs
items_dir =
jobs_to_keep = 5
dbs_dir = dbs
max_proc = 0
max_proc_per_cpu = 4
finished_to_keep = 100
poll_interval = 5.0
bind_address = 0.0.0.0
http_port = 6800
debug = off
runner = scrapyd.runner
application = scrapyd.app.application
launcher = scrapyd.launcher.Launcher
webroot = scrapyd.website.Root
[services]
schedule.json = scrapyd.webservice.Schedule
cancel.json = scrapyd.webservice.Cancel
addversion.json = scrapyd.webservice.AddVersion
listprojects.json = scrapyd.webservice.ListProjects
listversions.json = scrapyd.webservice.ListVersions
listspiders.json = scrapyd.webservice.ListSpiders
delproject.json = scrapyd.webservice.DeleteProject
delversion.json = scrapyd.webservice.DeleteVersion
listjobs.json = scrapyd.webservice.ListJobs
daemonstatus.json = scrapyd.webservice.DaemonStatus
上面的是官方提供的一個配置文件,這裏的修改僅僅是把bind_address由127.0.0.1修改爲了0.0.0.0,以使得外網可以訪問scrapyd。
3.Docker鏡像
接下來則是Dockerfile的編寫了。
首先可以在雲服務器上/home/下創建一個scrapy_test來保存配置文件和Dockerfile。項目結構如下:
在圖5中,Dockerfile爲構建docker鏡像的配置文件;requirements.txt爲 scrapyd所依賴的環境;而scrapyd.conf則是scrapyd運行所需的配置文件。
Dockerfile文件內容如下:
FROM python:3.7
ENV REFRESHED_AT 2019-05-30
ENV PATH /usr/local/bin:$PATH
#add the scrapyd configure file
ADD ./scrapyd.conf /etc/scrapyd/scrapyd.conf
#add requirements.txt
ADD requirements.txt /opt/requirements.txt
WORKDIR /opt
#use other fast image
RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
CMD ["scrapyd"]
EXPOSE 6800
首先,這個鏡像是基於python3.7的,所以需要先拉取鏡像:
docker pull python:3.7
其次,在環境中設置了一個REFRESHED_AT變量,由於docker build運行Dockerfile是每一個指令創建一個鏡像的,而指令內容的變化會使得從它開始的鏡像全都重新生成,所以可以通過修改REFRESHED_AT來控制鏡像的更新。
之後,把scrapyd.conf放到了/etc/scrapyd/目錄下,而requirements.txt 放到了/opt/目錄下(放在其他目錄也可以),然後設置/opt爲工作路徑,之後使用pip來安裝依賴環境。爲了使得pip下載庫更快一些而使用了清華的鏡像;
最後的CMD則是可以在docker run不添加命令的時候直接啓動scrapyd,最後則是暴露的6800端口。
然後就可以在本文件夾中使用docker build來構建鏡像了:
docker build -t xiaoniu/scrapyd .
構建成功後可以查看鏡像:
docker images
最後則是運行:
docker run -d -p 6800:6800 --name=scrapyd xiaoniu/scrapyd
-p 6800:6800表示的是開放容器的6800端口(這裏要確保主機的6800端口沒有被佔用),並把它和外部服務器的6800端口對應起來。
之後輸入:
docker ps -l
顯示:
可以看到我們創建的鏡像已經在運行了,並且開放了6800端口。
三.測試環境
如果服務器的6800端口已經開放(阿里雲需要手動開放端口,參考鏈接),則可以直接在瀏覽器訪問到scrapyd:
注意:如果scrapy和Twisted的版本不正確的話,Job網頁會出現錯誤.
四.Scrapyd-Client的安裝與操作
在終端環境下輸入下面的指令來安裝scrapyd-client:
pip install scrapyd-client
scrapyd-client的安裝最好是在非虛擬環境下,從圖2中可以看出,我們使用這個庫僅僅是爲了打包scrapy項目併發送給服務器,所以沒必要在虛擬環境下安裝。
安裝成功後會有一個可用的命令,叫做scrapyd-deploy,不過在windows下這個命令是無法直接用的。
首先,需要確定python的安裝位置,我這裏的安裝路徑爲:
C:\Users\lbb\AppData\Local\Programs\Python\Python37\Scripts
在這裏應該可以看到dcrapyd-deploy這個文件:
通過ubuntu的file命令(win10的應用商店中可以安裝ubuntu),可以稍微瞭解到這個文件的類型:
如果想執行的話,那麼還需要一個批處理文件scrapy-deploy.bat來執行這個python腳本:
@echo off
"C:\Users\lbb\AppData\Local\Programs\Python\Python37\python.exe" "C:\Users\lbb\AppData\Local\Programs\Python\Python37\Scripts\scrapyd-deploy" %1 %2 %3 %4 %5 %6 %7 %8 %9
注意:請根據自己的安裝路徑然後修改scrapy-deploy.bat腳本的路徑。
接着就可以打包併發送scrapy文件了。回到ScrapyTutorial的項目根目錄下,打開scrapy.cfg文件:
[settings]
default = tutorial.settings
[deploy:demo]
url = http://localhost:6800/
project = tutorial
把url的值改爲自己的服務器的IP地址。然後在項目根目錄下打開控制檯,輸入:
scrapyd-deploy demo -p tutorial
如果結果如下,則表示上傳到服務器成功!
接着可以在IP:6800上查看:
五.發起操作
從圖12中可以看到,scrapyd通過HTTP來發送請求的,而curl也可以發送HTTP請求,所以示例中使用到了curl。這裏同樣以curl爲例,注意把以下命令的localhost改爲服務器的IP地址。
1.獲取服務器狀態
curl http://localhost:6800/daemonstatus.json
2.運行爬蟲
curl http://localhost:6800/schedule.json -d project=tutorial -d spider=quotes
此時再看scrapyd的Jobs:
能夠發現開啓的爬蟲已經運行完畢,總共運行了8秒左右。
更多的命令請參考:https://scrapyd.readthedocs.io/en/latest/api.html
六.反向代理+身份驗證
配置完成後,Scrapyd和它的接口都是可以公開訪問的。如果想配置訪問認證的話,可以藉助於Nginx做反向代理。
雲服務器下docker部署scrapyd之二:使用Nginx對Scrapyd添加驗證
七.總結
1.curl的作用可以簡單的認爲和瀏覽器的作用差不多。
2.可以專門創建一個容器來對爬蟲進行管理,比如定時定點開啓爬蟲,這對於scrapyd是可以做到的。比如週一的凌晨2點到3點開始爬取數據,那麼我可以把這些數據寫入到容器的一個配置文件裏,然後在這個容器裏開啓一個進程,讓它一直檢測這個配置文件,來判斷是否需要開啓或者關閉爬蟲。
3.創建的scrapyd容器的requirements.txt僅僅包含了必要的庫,它並不能滿足所有的情況,如果一個其他的scrapy項目需要用到第三方庫,那麼在上傳的時候沒有問題,但是在運行的時候則會因爲找不到這個庫而出錯。解決辦法就是需要進入到scrapyd容器中手動加入某些庫。
參考鏈接:
scrapyd 問題 builtins.AttributeError: 'int' object has no attribute 'splitlines'