1. 程式人生 > 實用技巧 >15.1 Scrapyd 分散式部署

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 併成功執行,那麼我就可以在本地的瀏覽器中開啟:

http://120.27.34.25:6800,就可以看到 Scrapyd 的首頁,這裡請自行替換成你的伺服器地址檢視即可,如圖 15-1 所示:

圖 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 檔案然後再上傳,還是比較繁瑣的,在下一節我們介紹一個更加方便的工具來完成部署過程。