寫在前面:本篇文章內容較多,涉及知識較廣,讀完需要大約 20 分鐘,請讀者耐心閱讀。
如今大多數企業都離不開爬蟲,它是獲取資料的一種有效方式。但是對爬蟲有著規模量級要求的企業或個人需要同時處理不同類別的爬蟲,這會憑空增添很多附加的管理成本。同時,爬蟲管理者還需要應對網站內容變更、持續增量抓取、任務失敗等問題。因此一個成熟的爬蟲管理流程應該包含一個管理系統,能夠有效處理上述問題。
爬蟲有多重要
對搜尋引擎來說,爬蟲不可或缺;對輿情公司來說,爬蟲是基礎;對 NLP來說,爬蟲可以獲取語料;對初創公司來說,爬蟲可以獲取初始內容。但是爬蟲技術紛繁複雜,不同型別的抓取場景會運用到不同的技術。例如,簡單的靜態頁面可以用 HTTP 請求+HTML 解析器直接搞定;一個動態頁面需要用 Puppeteer 或 Selenium等自動化測試工具;有反爬的網站需要用到代理、打碼等技術;等等。那麼此時就需要一個成熟的爬蟲管理平臺,幫助企業或個人處理大量的爬蟲類別。
理解什麼是爬蟲管理平臺
定義
爬蟲管理平臺是一個一站式管理系統,集爬蟲部署、任務排程、任務監控、結果展示等模組於一體,通常配有視覺化 UI 介面,可以在 Web 端通過與 UI 介面互動來有效管理爬蟲。爬蟲管理平臺一般來說是支援分散式的,可以在多臺機器上協作執行。
當然,上述這個定義是狹義的,通常針對於技術人員或開發者或技術經理。企業內部一般都會開發自己的內部爬蟲管理系統,以應對複雜的爬蟲管理需求。這樣的系統就是上述定義的狹義的爬蟲管理平臺。
廣義爬蟲管理平臺
而什麼是廣義的爬蟲管理平臺呢?您可能聽說過神箭手(後轉型為后羿採集器)和八爪魚吧。前者是基於雲服務的,可以線上上編寫、執行和監控爬蟲,在廣義爬蟲平臺中最接近狹義定義的爬蟲管理平臺;後者是一個大眾的商業爬蟲抓取工具,可以讓小白使用者拖拉拽編寫、執行爬蟲,匯出資料。您也可能見過各種 API 聚合服務商,例如聚合資料,這是一個可以直接呼叫網站介面獲取資料的平臺,這其實也算作爬蟲平臺的一個變種,只是它幫你完成了爬蟲編寫這一過程。而介於這兩者之間的呢,國外有一家叫 Kimonolab 的公司,它開發了一個叫 Kimono 的 Chrome 外掛,可以讓使用者在頁面上視覺化的點選元素並生成抓取規則,並在其網站上生成爬蟲程式,使用者提交任務,後臺就可以自動在網站上抓取資料了。Kimono 是一個偉大的爬蟲應用,但可惜的是,Kimonolab 已經被大資料公司 Plantir 收購,現在也就無法體驗了。
在本文中,我們主要關注狹義定義的爬蟲管理平臺,因此後面所講到的爬蟲管理平臺都是指狹義的定義。
爬蟲管理平臺模組
以下是一個典型的爬蟲管理平臺所涉及的模組。
爬蟲管理平臺架構
典型爬蟲管理平臺的模組主要包含以下內容:
- 任務管理:如何執行、排程爬蟲抓取任務,以及如何監控任務,包括日誌監控等等;
- 爬蟲管理:包括爬蟲部署,即將開發好的爬蟲部署(打包或複製)到相應的節點上,以及爬蟲配置和版本管理;
- 節點管理:包括節點(伺服器/機器)的註冊和監控,以及節點之間的通訊,如何監控節點效能狀況等;
- 前端應用:包括一個視覺化 UI 介面,讓使用者可通過與其互動,與後臺應用進行通訊。
當然,有些爬蟲管理平臺可能還不止這些模組,它可能包括其他比較實用的功能,例如可配置的抓取規則、視覺化配置抓取規則、代理池、Cookie 池、異常監控等等。
為什麼需要爬蟲管理平臺
有了爬蟲管理平臺,開發者特別是爬蟲工程師就能夠方便的新增爬蟲、執行任務、檢視結果,而不用在命令列之間來回切換,非常容易出錯。一個常見的場景就是爬蟲工程師最初技術選型用了 scrapy 和 crontab 來管理爬蟲任務,他不得不小心翼翼的選擇定時任務的時間區間,以至於不會將伺服器 CPU 或記憶體佔滿;更棘手的問題是,他還需要將 scrapy 產生的日誌存到檔案裡,一旦爬蟲出錯了,他不得不用 shell 命令一個一個來檢視日誌來定位錯誤原因,嚴重時會花上一個整天;還有個嚴重的問題,爬蟲工程師可能發現公司業務量在增加,他需要寫上百個爬蟲來滿足公司的業務需求,而用 scrapy 和 crontab 來管理完全就是個噩夢。可憐的爬蟲工程師其實完全可以選擇一個合適爬蟲管理平臺來解決他的問題。
如何選擇一個合適的爬蟲管理平臺
當您願意解決前面提到的爬蟲工程師遇到的困難問題,而轉而想選擇一個合適的爬蟲管理平臺時。
您首先應該回答的問題是:我們是否需要從零開始開發一套系統(Start from scratch)?要回答這個問題,您應該先回答下面幾個問題:
- 我們的需求是否複雜到需要完全定製化開發一套新系統(例如要求複雜的許可權管理)?
- 我們的團隊是否有足夠的技術實力來開發這套系統(例如有經驗豐富的前後端開發工程師)?
- 我們的時間資源是否足夠我們開發這套系統(例如專案計劃週期為一年)?
如果上述三個問題的答案任意一個為“否”,您應該好好考慮利用市面上已有的開源爬蟲管理平臺來滿足您的需求。
以下為市面上已有的開源爬蟲管理平臺:
總的來說,SpiderKeeper 可能是最早的爬蟲管理平臺,但功能相對來說比較侷限;Gerapy 雖然功能齊全,介面精美,但有不少 bug 需要處理,建議有需求的使用者等待 2.0 版本;Scrapydweb是一個比較完善的爬蟲管理平臺,不過和前兩者一樣,都是基於 scrapyd 的,因此只能執行 scrapy 爬蟲;而Crawlab是一個非常靈活的爬蟲管理平臺,可以執行 Python、Nodejs、Java、PHP、Go 寫的爬蟲,而且功能比較齊全,只是部署起來相對於前三者來說要麻煩一些,不過對於 Docker 使用者來說可以做到一件部署(後面我們會講)。
因此,對於重度 scrapy 爬蟲依賴的、又不想折騰的開發者,可以考慮 Scrapydweb;而對於有各種型別的、複雜技術結構的爬蟲開發者來說,應該優先考慮更靈活的 Crawlab。當然,不是說 Crawlab 對 scrapy 支援不友好,Crawlab 同樣可以很好的整合 scrapy,後面會介紹。
作為 Crawlab 的作者,不想王婆賣瓜,自賣自誇,作者僅僅希望將最好的技術選型推薦給開發者,讓開發者根據自身的需求來決定該使用哪種爬蟲管理平臺。
爬蟲管理平臺 Crawlab 介紹
簡介
Crawlab 是基於 Golang 的分散式爬蟲管理平臺,支援 Python、NodeJS、Java、Go、PHP 等多種程式語言以及多種爬蟲框架。
Crawlab 自今年三月份上線以來受到爬蟲愛好者們和開發者們的好評,不少使用者還表示會用 Crawlab 搭建公司的爬蟲平臺。經過近數月的迭代,Crawlab 陸續上線了定時任務、資料分析、網站資訊、可配置爬蟲、自動提取欄位、下載結果、上傳爬蟲等功能,將平臺變得得更加實用,更加全面,能夠真正幫助使用者解決爬蟲管理困難的問題。如今在 Github 上有近 1k 的 star,相關社群也建立起來,四分之一的使用者表示已經將 Crawlab 應用於企業爬蟲管理。可以看出,Crawlab 是受開發者們關注和喜歡的。
解決問題
Crawlab 主要解決的是大量爬蟲管理困難的問題,例如需要監控上百個網站的參雜 scrapy 和 selenium 的專案不容易做到同時管理,而且命令列管理的成本非常高,還容易出錯。Crawlab 支援任何語言和任何框架,配合任務排程、任務監控,很容易做到對成規模的爬蟲專案進行有效監控管理。
介面及使用
下面是 Crawlab 爬蟲列表頁面的截圖。
Crawlab 爬蟲列表
使用者只需要將爬蟲上傳到 Crawlab,配置執行命令,點選“執行”按鈕,就可以執行爬蟲任務了。爬蟲任務可以在任何節點上執行。從上圖可以看到,Crawlab 有節點管理、爬蟲管理、任務管理、定時任務、使用者管理等模組。
整體架構
以下是 Crawlab 的整體架構圖,由五大部分組成:
- 主節點(Master Node):負責任務派發、API、部署爬蟲等;
- 工作節點(Worker Node):負責執行爬蟲任務;
- MongoDB 資料庫:儲存節點、爬蟲、任務等日常執行資料;
- Redis 資料庫:儲存任務訊息佇列、節點心跳等資訊。
- 前端客戶端:Vue 應用,負責前端互動和向後端請求資料。
Crawlab 架構
關於 Crawlab 如何使用和詳細原理超出了本篇文章的範圍,感興趣的可以去參考Github 主頁或相關文件。
Github地址及Demo
- 檢視演示 Demo
- Github: https://github.com/tikazyq/crawlab
使用 Docker 部署安裝 Crawlab
Docker 映象
Docker 是部署 Crawlab 最方便和簡潔的方式。其他部署方式包括直接部署,不過對於想快速搭建平臺的開發者來說不推薦。Crawlab 已在Dockerhub上註冊了相關的映象,開發者僅需要執行docker pull tikazyq/crawlab命令就可以將 Crawlab 的映象下載下來。
讀者可以去 Dockerhub 上檢視 Crawlab 的映象,只有僅不到 300Mb。地址:https://hub.docker.com/r/tikazyq/crawlab/tags
Dockerhub Page
安裝 Docker
要使用 Docker 來部署 Crawlab,您首先得保證 Docker 已經安裝好。請參考以下文件來安裝。
安裝 Docker Compose
Docker Compose 是簡單的執行 Docker 叢集的工具,非常輕量級,我們將用到 Docker Compose 來一鍵部署 Crawlab。
Docker 的官方網站已經有如何安裝 Docker Compose 的教程,點選連結檢視。這裡簡單介紹一下。
Linux 使用者請用以下命令安裝。
# 下載 docker-compose sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose` # 將 docker-compose 變成執行檔案 sudo chmod +x /usr/local/bin/docker-compose
拉取映象
在拉取映象之前,您需要配置一下映象源。因為在國內,使用原有的映象源速度不是很快,需要使用 DockerHub 在國內的加速器。請建立/etc/docker/daemon.json檔案,輸入如下內容。
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
然後拉取映象,就會快很多了。當然,您也可以用其他映象源,可以網上去搜尋一下。執行以下命令將 Crawlab 映象拉取下來。
docker pull tikazyq/crawlab:latest
下圖為拉取映象時的命令列介面。
docker pull
啟動 Crawlab
我們將用 Docker Compose 啟動 Crawlab 以及其依賴的資料庫 MongoDB 和 Redis。首先我們需要修改一下 Docker Compose 的 yaml 配置檔案docker-compose.yml。這個配置檔案定義了需要啟動的容器服務(Container Services)以及網路配置(Network Configuration)。這裡我們用 Crawlab 自帶的docker-compose.yml。
version: '3.3' # Docker Compose 的版本號(請看後續說明) services: # 服務 master: # 服務名稱 image: tikazyq/crawlab:latest # 服務對應的映象名稱 container_name: master # 服務對應的容器名稱 environment: # 這裡定義傳入的環境變數 CRAWLAB_API_ADDRESS: "localhost:8000" # 前端呼叫的 API 地址,預設為 localhost:8000 CRAWLAB_SERVER_MASTER: "Y" # 是否為主節點,Y/N CRAWLAB_MONGO_HOST: "mongo" # MongoDB host,由於在 Docker Compose 裡,可以引用服務名稱 CRAWLAB_REDIS_ADDRESS: "redis" # Redis host,由於在 Docker Compose 裡,可以引用服務名稱 ports: # 對映的埠 - "8080:8080" # 前端埠 - "8000:8000" # 後端埠 depends_on: # 依賴的服務 - mongo # MongoDB - redis # Redis worker: # 工作節點,與主節點配置類似,不重複寫了 image: tikazyq/crawlab:latest container_name: worker environment: CRAWLAB_SERVER_MASTER: "N" CRAWLAB_MONGO_HOST: "mongo" CRAWLAB_REDIS_ADDRESS: "redis" depends_on: - mongo - redis mongo: # MongoDB 服務名稱 image: mongo:latest # MongoDB 映象名稱 restart: always # 重啟策略為“總是” ports: # 對映埠 - "27017:27017" redis: # Redis 服務名稱 image: redis:latest # Redis 映象名稱 restart: always # 重啟策略為“總是” ports: # 對映埠 - "6379:6379"
讀者可以根據自己的要求來配置docker-compose.yml。尤其需要注意CRAWLAB_API_ADDRESS這個環境變數,很多初學使用者都是因為該變數配置不正確而導致無法登陸。大多數情況,您不用做任何配置更改。請參考Q&A來處理常見問題,以及詳細的環境變數配置文件來幫助根據自身環境配置 Crawlab。
然後,執行下列命令啟動 Crawlab。可以加一個-d引數讓 Docker Compose 後臺執行。
docker-compose up
執行上述命令後,Docker Compose 會去拉取 MongoDB 和 Redis 的映象,這可能會花幾分鐘時間。拉取完畢後,四個服務會依次啟動,您將會在命令列中看到如下內容。
docker-compose
正常情況下,您應該可以看到四個服務都啟動成功,並能夠順利列印日誌。
如果您是在本機上啟動的 Docker Compose,可以在瀏覽器中輸入http://localhost:8080,然後就能看到登陸介面了;如果您是在其他機器上啟動的 Docker Compose,您需要在瀏覽器中輸入http://<your_ip>:8080來看到登陸介面,<your_ip>是其他機器的 IP 地址(請保證 8080 埠在該機器已對外開放)。
login
初始登陸使用者名稱密碼是 admin/admin,您可以使用這個使用者名稱密碼來登陸。如果您的環境變數CRAWLAB_API_ADDRESS設定得不正確,您可能會看到點選登陸後登陸按鈕會一直轉圈而沒有任何提示。這時請重新在docker-compose.yml中設定正確的CRAWLAB_API_ADDRESS(將localhost替換為<your_ip>),重新啟動docker-compose up。然後在瀏覽器中輸入http://<your_ip>:8080。
登陸之後您將看到 Crawlab 的主頁。
home
本篇文章主要介紹如何搭建爬蟲管理平臺 Crawlab,因此不會詳細介紹如何使用 Crawlab(可能會建立另一篇文章來詳細介紹,有興趣者可以關注一下)。如果您有困惑,請檢視相關文件來了解如何使用。
如何將 Scrapy 等爬蟲整合到 Crawlab
眾所周知,Scrapy 是非常受歡迎的爬蟲框架,其靈活的框架設計、高併發、易用性以及可擴充套件性讓很多開發者和企業大量採用。市面上的爬蟲管理平臺幾乎都支援 Scrapy 爬蟲,Crawlab 也不例外,但 Crawlab 可以執行 puppeteer、selenium 等其他爬蟲。下面將介紹一下在 Crawlab 中如何執行 scrapy 爬蟲。
Crawlab 是執行爬蟲基本原理
Crawlab 執行爬蟲的原理很簡單,其實就是一個 shell 命令。使用者在爬蟲中輸入執行爬蟲的 shell 命令,例如scrapy crawl some_spider,Crawlab 執行器會讀取這個命令,並在 shell 中直接執行。因此,每一次執行爬蟲任務,就是執行了一次 shell 命令(當然,實際情況要比這個複雜很多,感興趣的可以去參考官方文件)。Crawlab 是支援展示和匯出爬蟲結果的,不過這需要稍微多做一些工作。
編寫 Pipeline
要整合 scrapy 爬蟲,無非就是將爬蟲抓取的資料存到 Crawlab 的資料庫裡,然後用任務 ID 關聯起來。每次執行爬蟲任務,任務 ID 會通過環境變數傳到爬蟲程式中,因此我們需要做的就是將任務 ID 加上結果存到資料庫裡(Crawlab 現在只支援 MongoDB,後期會開發 MySQL、SQL Server、Postgres 等關係型資料庫,有需求的使用者可以關注一下)。
在 Scrapy 中,我們需要編寫儲存邏輯。示意程式碼如下:
# 引入相關的庫,pymongo 是標準連線 MongoDB 的庫 import os from pymongo import MongoClient # MongoDB 配置引數 MONGO_HOST = '192.168.99.100' MONGO_PORT = 27017 MONGO_DB = 'crawlab_test' class JuejinPipeline(object): mongo = MongoClient(host=MONGO_HOST, port=MONGO_PORT) # mongo 連線例項 db = mongo[MONGO_DB] # 資料庫例項 col_name = os.environ.get('CRAWLAB_COLLECTION') # 集合名稱,通過環境變數 CRAWLAB_COLLECTION 傳過來 # 如果 CRAWLAB_COLLECTION 不存在,則預設集合名稱為 test if not col_name: col_name = 'test' col = db[col_name] # 集合例項 # 每一個傳入 item 會呼叫的函式,引數分別為 item 和 spider def process_item(self, item, spider): item['task_id'] = os.environ.get('CRAWLAB_TASK_ID') # 將 task_id 設定為環境變數傳過來的任務 ID self.col.save(item) # 儲存 item 在資料庫中 return item
同時,您也需要在items.py中加入task_id欄位,已保證值能夠被賦上(這很重要)。
上傳並配置爬蟲
在執行爬蟲之前,您需要上傳爬蟲檔案到主節點。步驟如下:
- 將爬蟲檔案打包成 zip(注意,要保證在根目錄下直接打包);
- 在側邊欄點選“爬蟲”導航至爬蟲列表,點選“新增爬蟲”按鈕,選擇“自定義爬蟲”;
- 點選“上傳”按鈕,選擇剛剛打包好的 zip 檔案
- 上傳成功後,爬蟲列表中會出現新新增的自定義爬蟲,這樣就算上傳成功了。
可以在爬蟲詳情中點選“檔案”標籤,選擇一個檔案,可以在檔案中編輯程式碼。
接下來,您需要在“概覽”標籤中的“執行命令”一欄輸入爬蟲的 shell 執行命令。Crawlab 的 Docker 映象裡是內建了 scrapy 的,因此可以直接執行 scrapy 爬蟲。命令就是scrapy crawl <some_spider>。點選“儲存”按鈕儲存爬蟲配置。
執行爬蟲任務
然後就是執行爬蟲任務了。其實很簡單,在“概覽”標籤中點選“執行”按鈕,爬蟲任務就開始執行了。如果日誌提示找不到 scrapy 命令,可以將scrapy改為絕對路徑/usr/local/bin/scrapy,這樣就會執行成功。
任務執行情況會在“任務”頁面或者爬蟲“概覽”裡展現,會每 5 秒鐘更新一次,大家可以在這上面檢視。而且在爬蟲“結果”標籤裡,可以預覽結果的詳情,還可以匯出資料成 CSV 檔案。
構建持續整合(CI)工作流
對於企業來說,軟體開發一般是一個自動化過程。它會經歷需求、開發、部署、測試、上線這幾個步驟。而這個流程一般是不斷迭代(Iterative)的,需要不斷更新和釋出。
以爬蟲為例,您上線了一個爬蟲,這個爬蟲會定期抓取網站資料。但突然有一天您發現資料抓不到了,您快速定位原因,發現原來是網站改版了,您需要更改爬蟲抓取規則來應對網站的改版。總之,您需要釋出一個程式碼更新。最快的做法是直接線上上更改程式碼。但這樣做非常危險:第一,您無法測試您更新後的程式碼,只能通過不斷調整線上程式碼來測試是否抓取成功;第二,您無法記錄這次更改,後期如果出了問題您很可能會忽略掉這次更改,從而導致 bug。您需要做的,無非是將您的爬蟲程式碼用版本管理工具管理起來。我們有很多版本管理工具,最常用的就是 git、subversion,版本管理平臺包括 Gitlab、Bitbucket、自搭 Git 倉庫等。
當我們更新了程式碼,我們需要將更新後的程式碼釋出到線上伺服器。這時您需要用自己寫部署指令碼,或者更方便的,用 Jenkins 作為持續整合(Continuous Integration)管理平臺。Jenkins 是一個持續整合平臺,可以通過獲取版本庫來更新部署程式碼,是非常實用的工具,在很多企業中都有用到。下圖是如何將 Crawlab 爬蟲應用到持續整合工作流程中的例子。
ci
要在 Crawlab 中建立或更新爬蟲有兩種方式:
- 上傳打包成後的 zip 檔案;
- 通過更改主節點中目錄CRAWLAB_SPIDER_PATH中的爬蟲檔案。
我們做持續整合,就是針對第二種方式。步驟如下:
- 用 Gitlab 或其他平臺搭建好程式碼倉庫;
- 在 Jenkins 中建立一個專案,在專案中將程式碼源指向之前建立的倉庫;
- 在 Jenkins 專案中編寫工作流,將釋出地址指向 Crawlab 的CRAWLAB_SPIDER_PATH,如果是 Docker 注意將該地址掛載到宿主機檔案系統;
- Jenkins 專案的工作可以直接編寫,也可以用 Jenkinsfile,具體可以查相關資料;
- 這樣,每一次程式碼更新提交到程式碼倉庫後,Jenkins 就會將更新後的程式碼釋出到 Crawlab 裡,Crawlab 主節點會將爬蟲程式碼同步到工作節點,以待抓取。
總結
本篇文章主要介紹了爬蟲管理平臺的定義、如何選擇爬蟲管理平臺,著重介紹瞭如何搭建開源爬蟲管理平臺 Crawlab,另外還講到了如何整合 scrapy 爬蟲以及如何打造持續整合工作流。本篇文章沒有涉及到的內容還有很多,包括如何 Crawlab 的原理和架構詳情、如何使用 Crawlab、如何編寫大規模爬蟲、如何使用 Jenkins 等等。這些內容可能會在其他文章中釋出,請感興趣的讀者多多關注。另外,Crawlab 還有一些需要提升的地方,例如異常監控(零值、空值)、可配置爬蟲、視覺化抓取、日誌集中收集等等。這些功能都將在以後陸續開發和釋出,請大家也多多關注。
本文分享自華為雲社群《如何快速搭建實用的爬蟲管理平臺》,原文作者:Marvin Zhang。