15.1 Scrapyd 分散式部署
15.1 Scrapyd 分散式部署
分散式爬蟲完成並可以成功運行了,但是有個環節非常煩瑣,那就是程式碼部署。
我們設想下面的幾個場景。
-
如果採用上傳檔案的方式部署程式碼,我們首先將程式碼壓縮,然後採用 SFTP 或 FTP 的方式將檔案上傳到伺服器,之後再連線伺服器將檔案解壓,每個伺服器都需要這樣配置。
-
如果採用 Git 同步的方式部署程式碼,我們可以先把程式碼 Push 到某個 Git 倉庫裡,然後再遠端連線各臺主機執行 Pull 操作,同步程式碼,每個伺服器同樣需要做一次操作。
如果程式碼突然有更新,那我們必須更新每個伺服器,而且萬一哪臺主機的版本沒控制好,這可能會影響整體的分散式爬取狀況。
所以我們需要一個更方便的工具來部署 Scrapy 專案,如果可以省去一遍遍逐個登入伺服器部署的操作,那將會方便很多。
本節我們就來看看提供分散式部署的工具 Scrapyd。
1. 瞭解 Scrapyd
Scrapyd 是一個執行 Scrapy 爬蟲的服務程式,它提供一系列 HTTP 介面來幫助我們部署、啟動、停止、刪除爬蟲程式。Scrapyd 支援版本管理,同時還可以管理多個爬蟲任務,利用它我們可以非常方便地完成 Scrapy 爬蟲專案的部署任務排程。
2. 準備工作
請確保本機或伺服器已經正確安裝好了 Scrapyd,安裝和配置的方法可以參見第 1 章的內容。
3. 訪問 Scrapyd
安裝並運行了 Scrapyd 之後,我們就可以訪問伺服器的 6800 埠看到一個 WebUI 頁面了,例如我的伺服器地址為 120.27.34.25,在上面安裝好了 Scrapyd 併成功執行,那麼我就可以在本地的瀏覽器中開啟:
圖 15-1 Scrapyd 首頁
如果可以成功訪問到此頁面,那麼證明 Scrapyd 配置就沒有問題了。
4. Scrapyd 的功能
Scrapyd 提供了一系列 HTTP 介面來實現各種操作,在這裡我們可以將介面的功能梳理一下,以 Scrapyd 所在的 IP 為 120.27.34.25 為例:
daemonstatus.json
這個介面負責檢視 Scrapyd 當前的服務和任務狀態,我們可以用 curl 命令來請求這個介面,命令如下:
curl http://139.217.26.30:6800/daemonstatus.json
這樣我們就會得到如下結果:
{"status": "ok", "finished": 90, "running": 9, "node_name": "datacrawl-vm", "pending": 0}
返回結果是 Json 字串,status 是當前執行狀態, finished 代表當前已經完成的 Scrapy 任務,running 代表正在執行的 Scrapy 任務,pending 代表等待被排程的 Scrapyd 任務,node_name 就是主機的名稱。
addversion.json
這個介面主要是用來部署 Scrapy 專案用的,在部署的時候我們需要首先將專案打包成 Egg 檔案,然後傳入專案名稱和部署版本。
我們可以用如下的方式實現專案部署:
curl http://120.27.34.25:6800/addversion.json -F project=wenbo -F version=first -F [email protected]
在這裡 -F 即代表新增一個引數,同時我們還需要將專案打包成 Egg 檔案放到本地。
這樣發出請求之後我們可以得到如下結果:
{"status": "ok", "spiders": 3}
這個結果表明部署成功,並且其中包含的 Spider 的數量為 3。
此方法部署可能比較繁瑣,在後文會介紹更方便的工具來實現專案的部署。
schedule.json
這個介面負責排程已部署好的 Scrapy 專案執行。
我們可以用如下介面實現任務排程:
curl http://120.27.34.25:6800/schedule.json -d project=weibo -d spider=weibocn
在這裡需要傳入兩個引數,project 即 Scrapy 專案名稱,spider 即 Spider 名稱。
返回結果如下:
{"status": "ok", "jobid": "6487ec79947edab326d6db28a2d86511e8247444"}
status 代表 Scrapy 專案啟動情況,jobid 代表當前正在執行的爬取任務代號。
cancel.json
這個介面可以用來取消某個爬取任務,如果這個任務是 pending 狀態,那麼它將會被移除,如果這個任務是 running 狀態,那麼它將會被終止。
我們可以用下面的命令來取消任務的執行:
curl http://120.27.34.25:6800/cancel.json -d project=weibo -d job=6487ec79947edab326d6db28a2d86511e8247444
在這裡需要傳入兩個引數,project 即專案名稱,job 即爬取任務代號。
返回結果如下:
{"status": "ok", "prevstate": "running"}
status 代表請求執行情況,prevstate 代表之前的執行狀態。
listprojects.json
這個介面用來列出部署到 Scrapyd 服務上的所有專案描述。
我們可以用下面的命令來獲取 Scrapyd 伺服器上的所有專案描述:
curl http://120.27.34.25:6800/listprojects.json
這裡不需要傳入任何引數。
返回結果如下:
{"status": "ok", "projects": ["weibo", "zhihu"]}
status 代表請求執行情況,projects 是專案名稱列表。
listversions.json
這個介面用來獲取某個專案的所有版本號,版本號是按序排列的,最後一個條目是最新的版本號。
我們可以用如下命令來獲取專案的版本號:
curl http://120.27.34.25:6800/listversions.json?project=weibo
在這裡需要一個引數 project,就是專案的名稱。
返回結果如下:
{"status": "ok", "versions": ["v1", "v2"]}
status 代表請求執行情況,versions 是版本號列表。
listspiders.json
這個介面用來獲取某個專案最新的一個版本的所有 Spider 名稱。
我們可以用如下命令來獲取專案的 Spider 名稱:
curl http://120.27.34.25:6800/listspiders.json?project=weibo
在這裡需要一個引數 project,就是專案的名稱。
返回結果如下:
{"status": "ok", "spiders": ["weibocn"]}
status 代表請求執行情況,spiders 是 Spider 名稱列表。
listjobs.json
這個介面用來獲取某個專案當前執行的所有任務詳情。
我們可以用如下命令來獲取所有任務詳情:
curl http://120.27.34.25:6800/listjobs.json?project=weibo
在這裡需要一個引數 project,就是專案的名稱。
返回結果如下:
{"status": "ok",
"pending": [{"id": "78391cc0fcaf11e1b0090800272a6d06", "spider": "weibocn"}],
"running": [{"id": "422e608f9f28cef127b3d5ef93fe9399", "spider": "weibocn", "start_time": "2017-07-12 10:14:03.594664"}],
"finished": [{"id": "2f16646cfcaf11e1b0090800272a6d06", "spider": "weibocn", "start_time": "2017-07-12 10:14:03.594664", "end_time": "2017-07-12 10:24:03.594664"}]}
status 代表請求執行情況,pendings 代表當前正在等待的任務,running 代表當前正在執行的任務,finished 代表已經完成的任務。
delversion.json
這個介面用來刪除專案的某個版本。
我們可以用如下命令來刪除專案版本:
curl http://120.27.34.25:6800/delversion.json -d project=weibo -d version=v1
在這裡需要一個引數 project,就是專案的名稱,還需要一個引數 version,就是專案的版本。
返回結果如下:
{"status": "ok"}
status 代表請求執行情況,這樣就代表刪除成功了。
delproject.json
這個介面用來刪除某個專案。
我們可以用如下命令來刪除某個專案:
curl http://120.27.34.25:6800/delproject.json -d project=weibo
在這裡需要一個引數 project,就是專案的名稱。
返回結果如下:
{"status": "ok"}
status 代表請求執行情況,這樣就代表刪除成功了。
以上就是 Scrapyd 所有的介面,我們可以直接請求 HTTP 介面即可控制專案的部署、啟動、執行等操作。
5. ScrapydAPI 的使用
以上的這些介面可能使用起來還不是很方便,沒關係,還有一個 ScrapydAPI 庫對這些介面又做了一層封裝,其安裝方式也可以參考第一章的內容。
下面我們來看下 ScrapydAPI 的使用方法,其實核心原理和 HTTP 介面請求方式並無二致,只不過用 Python 封裝後使用更加便捷。
我們可以用如下方式建立一個 ScrapydAPI 物件:
from scrapyd_api import ScrapydAPI
scrapyd = ScrapydAPI('http://120.27.34.25:6800')
然後就可以呼叫它的方法來實現對應介面的操作了,例如部署的操作可以使用如下方式:
egg = open('weibo.egg', 'rb')
scrapyd.add_version('weibo', 'v1', egg)
這樣我們就可以將專案打包為 Egg 檔案,然後把本地打包的的 Egg 專案部署到遠端 Scrapyd 了。
另外 ScrapydAPI 還實現了所有 Scrapyd 提供的 API 介面,名稱都是相同的,引數也是相同的。
例如我們可以呼叫 list_projects() 方法即可列出 Scrapyd 中所有已部署的專案:
scrapyd.list_projects()
['weibo', 'zhihu']
另外還有其他的方法在此不再一一列舉了,名稱和引數都是相同的,更加詳細的操作可以參考其官方文件:http://python-scrapyd-api.readthedocs.io/。
6. 結語
本節介紹了 Scrapyd 及 ScrapydAPI 的相關用法,我們可以通過它來部署專案,並通過 HTTP 介面來控制人物的執行,不過這裡有一個不方便的地方就是部署過程,首先它需要打包 Egg 檔案然後再上傳,還是比較繁瑣的,在下一節我們介紹一個更加方便的工具來完成部署過程。