?

基于Django 的分布式爬蟲框架設計與實現*

2020-12-07 05:26劉建華
計算機與數字工程 2020年10期
關鍵詞:爬蟲隊列實例

趙 宸 劉建華

(西安郵電大學 西安 710121)

1 引言

網絡爬蟲[9]是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本,目前主流的爬蟲框架Nutch、Crawler4j、WebMagic、scrapy、WebCollector均沒有在運行的爬蟲中實時更新代碼并自動重新載入的功能,本文利用Django 框架[2]中自動重載機制,使用Python[6]語言開發了分布式[4~5]、多進程爬蟲框架[1],實現了可在運行的爬蟲中實時更新代碼并自動重新載入內存執行的功能,同時,根據下載過程中的斷點續傳[7]思想,使用Redis[3,16]開發了任務隊列技術,實現了重新載入爬蟲代碼后從斷點恢復任務狀態并繼續執行后續任務的功能,并解決了重新載入后數據丟失問題。實驗表明,爬蟲框架可識別爬蟲代碼變化并重新載入到內存運行,重新載入后不會丟失數據,且相對其他分布式網絡爬蟲,性能提升了40.7%,節約了數據獲取成本。

2 框架設計

爬蟲框架基于Django框架開發,由集中式的爬蟲服務和任務隊列以及分布式的爬蟲實例構成,并利用了Django 框架的ORM[10]封裝了數據處理模塊。如圖1 所示,爬蟲服務將用戶初始任務存入任務隊列中,由分布式爬蟲實例中的爬蟲主進程獲取并分配給爬蟲子進程執行與處理,所有爬蟲實例的結構與內容相同,保證了任務處理的負載均衡。

爬蟲實例由爬蟲主進程、爬蟲子進程、任務模塊、數據處理模塊、抓取器、下載器、解析器、日志模塊和各站點爬蟲組成等組成,所有模塊均可調用日志模塊并輸出日志。爬蟲實例執行任務流程使用偽代碼描述如下:

圖1 爬蟲框架結構圖

3 系統實現

3.1 可重載的爬蟲實例

首先,Django框架的自動重載機制[11]實現原理是每隔1 秒根據每個文件的最后修改時間來判斷文件是否被修改,如果修改,則退出舊進程,啟動新進程執行修改后的代碼。爬蟲實例的自動重載基于這一原理實現,首先,將爬蟲框架的基本組件和爬蟲文件組織成Django 項目中的APP 包,如圖2 所示。然后,改寫Django 的命令行模塊,使原來的啟動站點服務的命令行功能變成執行爬蟲主進程,并設置運行參數為“—reload”,從而將爬蟲框架和爬蟲代碼列入自動重載機制中,這樣更新爬蟲代碼時,Django 框架會通過重載重新執行爬蟲主進程,從而執行新的爬蟲代碼。

圖2 爬蟲實例結構

3.2 任務隊列

在分布式環境下,爬蟲主進程重新載入后,為了找回斷點以及防止正在執行的任務丟失,本文利用Redis設計了爬蟲框架的任務隊列系統。

如圖3 所示,除了“任務隊列”,還設計了“本地正在執行的任務隊列”。爬蟲主進程將調度成功的任務同步寫入“本地正在執行的任務隊列”,發生爬蟲主進程重載時,會重新執行“本地正在執行的任務隊列”中的任務,當爬蟲子進程完成任務后會從該隊列中刪除任務。同時,為了保證重新載入過程中不對數據讀寫產生影響,框架中對Redis 和數據庫的操作兼具備原子性[12],使用管道技術讀寫Re?dis 以及封裝數據庫讀寫都保證了重新載入時的操作回滾。

圖3 Redis任務隊列

初始任務在寫入任務隊列時,由框架分配唯一ID,爬蟲由此任務不斷產生的新任務共用這個ID,在分布式環境中,爬蟲主進程判斷一個任務完成的標志由式(1)計算得出,其中,NR為此ID 任務剩余數量,NA為新任務數量,每個分布式爬蟲實例新增一個任務,即增1,NF為已完成的任務數量,在爬蟲子進程釋放資源時設置,NE為出錯的任務數量,判斷此ID 任務完成的條件為:NR=0。例如,完成初始任務后,產生一個新任務,則在釋放資源前對NA進行加一操作,此時NR為1>0。在完成非初始任務的這個任務后,如果又產生2 個新任務,則在釋放資源前先經行NF增1 操作,并對NR進行增2 操作,此時NR為2>0。當完成新產生的2 個任務且未產生新任務時,做NF增2 操作,此時NR為0,可判斷任務結束。

4 框架測試與分析

4.1 自動重載測試

測試目的:測試分布式爬蟲實例在運行過程中更新代碼,是否可以自動重新載入且不丟失數據。

測試環境:在內網IP 末尾分別為239 和240 兩臺Linux 服務器[13]上部署爬蟲實例,在239 服務器上部署爬蟲服務和任務隊列。

測試方法:發送4個相同的爬蟲任務,在240節點爬蟲實例運行過程中,多次使用git[14~15]將添加了空格的爬蟲代碼從代碼倉庫直接同步到本地,測試爬蟲實例自動重新載入的情況。

測試結果:如圖4 所示,代碼發生變化后,運行中的爬蟲實例實現了自動重新載入。由圖5 可知,在分布式環境中,4 個相同的任務在有爬蟲節點重載的情況下,最終獲取的數據數量相同。

圖4 爬蟲重載測試

圖5 爬蟲重載測試結果

結論:運行中的爬蟲實例可在代碼更新后實現自動重新載入,并且任意時刻的重新載入不會對數據結果產生影響。

4.2 爬蟲性能測試

測試目的:測試爬蟲獲取數據的速度,并與已有分布式爬蟲對比。

測試環境:為保證對比測試環境統一,調整測試環境:Cpu核心數為12個,網絡1Gbps,內存8G。

測試方法:運行鏈家二手房爬蟲,發送“上海市”關鍵詞為初始任務,爬取上海市鏈家站點的全部二手房掛牌房源信息,每條房源數據需分別請求詳細頁和過去看房次數頁面。

測試結果:圖6 中方框分別對應第一條數據和最后一條數據的入庫時間,由此可見,框架中的爬蟲在約77min左右的時間內獲取了54256條房源信息,平均1 秒11.725 條數據,即下載速度約為23.451(URL/s),平均單進程單頁面耗時1.023s。

結論:相比其他分布式網絡爬蟲[8]同等測試環境下的16.666(URL/s)下載速度,該框架下的爬蟲下載速度提升了(23.451-16.666)/16.666=40.7%的性能。

圖6 上海鏈家二手房數據

5 結語

該爬蟲框架是一個多進程、分布式的爬蟲框架,借助Django 框架特性,具有隨時更新爬蟲代碼后自動重新載入的功能,并且重新載入過程中不會丟數據,可使用腳本批量更新集群中的爬蟲代碼,使得爬蟲的開發和維護變的十分方便,同時相較其他分布式爬蟲方案,本文框架可提升爬蟲40.7%的性能,降低了數據獲取成本。

猜你喜歡
爬蟲隊列實例
利用網絡爬蟲技術驗證房地產灰犀牛之說
基于Python的網絡爬蟲和反爬蟲技術研究
隊列隊形體育教案
隊列里的小秘密
基于多隊列切換的SDN擁塞控制*
在隊列里
基于Scrapy框架的分布式網絡爬蟲的研究與實現
誰搶走了低價機票
完形填空Ⅱ
完形填空Ⅰ
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合