Scrapy分散式、去重增量爬蟲的開發與設計
基於 python 分散式房源資料抓取系統為資料的進一步應用即房源推薦系統做資料支援。本課題致力於解決單程序單機爬蟲的瓶頸,打造一個基於 Redis 分散式多爬蟲共享佇列的主題爬蟲。本系統採用 python 開發的 Scrapy 框架來開發,使用 Xpath 技術對下載的網頁進行提取解析,運用 Redis 資料庫做分散式,使用MongoDb 資料庫做資料儲存,利用 Django web 框架和 Semantic UI開源框架對資料進行友好視覺化,最後使用了Docker對爬蟲程式進行部署。設計並實現了針對 58 同城各大城市租房平臺的分散式爬蟲系統。

分散式爬蟲抓取系統主要包含以下功能:
1.爬蟲功能: 爬取策略的設計 內容資料欄位的設計 增量爬取 請求去重
2.中介軟體: 爬蟲防遮蔽中介軟體 網頁非200狀態處理 爬蟲下載異常處理
3.資料儲存: 抓取欄位設計 資料儲存
4.資料視覺化
完整專案原始碼
關注微信公眾號 datayx 然後回覆 分散式 即可獲取。
二、系統分散式架構
分散式採用主從結構設定一個Master伺服器和多個Slave伺服器,Master端管理Redis資料庫和分發下載任務,Slave部署Scrapy爬蟲提取網頁和解析提取資料,最後將解析的資料儲存在同一個MongoDb資料庫中。分散式爬蟲架構如圖所示。

應用Redis資料庫實現分散式抓取,基本思想是Scrapy爬蟲獲取的到的detail_request的urls都放到Redis Queue中,所有爬蟲也都從指定的Redis Queue中獲取requests,Scrapy-Redis元件中預設使用SpiderPriorityQueue來確定url的先後次序,這是由sorted set實現的一種非FIFO、LIFO方式。因此,待爬佇列的共享是爬蟲可以部署在其他伺服器上完成同一個爬取任務的一個關鍵點。此外,在本文中,為了解決Scrapy單機侷限的問題,Scrapy將結合Scrapy-Redis元件進行開發,Scrapy-Redis總體思路就是這個工程通過重寫Scrapu框架中的scheduler和spider類,實現了排程、spider啟動和redis的互動。實現新的dupefilter和queue類,達到了判重和排程容器和redis的互動,因為每個主機上的爬蟲程序都訪問同一個redis資料庫,所以排程和判重都統一進行統一管理,達到了分散式爬蟲的目的。
三、系統實現
1)爬取策略的設計 由scrapy的結構分析可知,網路爬蟲從初始地址開始,根據spider中定義的目標地址獲的正則表示式或者Xpath獲得更多的網頁連結,並加入到待下載隊列當中,進行去重和排序之後,等待排程器的排程。 在這個系統中,新的連結可以分為兩類,一類是目錄頁連結,也就是我們通常看到的下一頁的連結,一類是內容詳情頁連結,也就是我們需要解析網頁提取欄位的連結,指向的就是實際的房源資訊頁面。網路需從每一個目錄頁連結當中,提取到多個內容頁連結,加入到待下載佇列準備進一步爬取。
此處是Master端的目標連結的爬取策略,因為採取的分散式主從模式,Master端爬蟲主要爬取下載到內容詳情頁連結,通過redis分享下載任務給其他slave端的爬蟲。Slave端主要是負責對詳情頁連結的進一步解析提取儲存到資料庫中。 本論文以58同城租房為例,其初始頁連結,其實也就是每個分類的第一頁連結,主要有(以廣東省幾個城市為例):
綜上所述,網路房源爬取系統使用以下爬取策略:
1) 對於Master端: 最核心模組是解決翻頁問題和獲取每一頁內容詳情頁連結。
Master端主要採取以下爬取策略:
1. 向redis往key為nest_link插入初始連結,從初始頁連結開始
2. 爬蟲從redis中key為next_link中取到初始連結,開始執行爬蟲
3. 將下載器返回的Response,爬蟲根據spider定義的爬取規則識別是否有下一頁連結,若有連結,儲存進redis中,儲存key為next_link,同時根據匹配規則是否匹配到多個內容詳情頁連結,若匹配到,則儲存進Redis,儲存key為detail_request插入下載連結,給slave端的spider使用,即是Slave端的下載任務。
4. 爬蟲繼續從redis中key為next_link取值,若有值,繼續步驟2,若為空,爬蟲則等待新的連結。
2) 對於Slave端: 最核心模組是從redis獲得下載任務,解析提取欄位。Slave端主要採取以下爬取策略:
1.爬蟲從redis中key為detail_request中取到初始連結,開始執行爬蟲
2.將下載器返回的Response,爬蟲根據spider定義的爬取規則識別是否有匹配規則的內容欄位,若有將欄位儲存,返回到模型中,等待資料儲存操作。 重複步驟1,直到帶爬取佇列為空,爬蟲則等待新的連結。
2)爬蟲的具體實現
爬蟲程式的包含四個部分,分別是物件定義程式,資料抓取程式,資料處理程式和下載設定程式,此處的組成是Slave端,Master少了物件定義程式以及資料處理程式,Master端主要是下載連結的爬取。
(1)資料抓取程式 資料抓取程式分Master端和Slave端,資料抓取程式從Redis中獲得初始地址,資料抓取程式中定義了抓取網頁的規則和使用Xpath提取欄位資料的方法等,這裡著重介紹Xpath提取字元資料的方法,Xapth使用路徑表示式來選取網頁文件中的節點或者節點集。在Xpath中有其中型別的幾點:元素、屬性、文字、名稱空間、處理指令、註釋和文件節點。網頁文件是被當做節點樹來對待,樹的跟被稱為文件節點和根節點,通過Xpath表示式定位目標節點即可抽取網頁文件的欄位資料。
3)去重與增量爬取
去重與增量爬取,對於伺服器有很重大的意義,能夠減少伺服器的壓力以及保證資料的準確性。如果不採取去重處理,那麼抓取的內容會抓取大量重複內容,讓爬蟲效率極大的下降。其實去重流程很簡單,核心就是每次請求的時候,先判斷這個請求是否在已經爬取的隊列當中。如果已存在,則捨棄當前請求。 具體實現步驟:

(1) 從待爬佇列中獲取url
(2) 將即將請求的url判斷是否已經爬取,若已爬取,則將請求忽略,未爬取,繼續其他操作並將url插入已爬取佇列中
(3) 重複步驟1 這裡我們使用scrapy-redis的去重元件,所以也沒有實現,不過原理還是要看懂的,具體可以看原始碼。
4)爬蟲中介軟體
爬蟲中介軟體能夠幫助我們在scrapy抓取流程中自由的擴充套件自己的程式,以下有爬蟲防遮蔽中介軟體,下載器異常狀態中介軟體以及非200狀態中介軟體。
(1)爬蟲防遮蔽元件的實現 訪問一個網站的網頁的時候,會給網站帶了一定的負載,而爬蟲程式則是模擬了我們正常訪問網頁的過程,但是。大規模的爬蟲會給網站增加大量的負載,影響正常使用者的訪問。為保證網頁能夠別大多數正常使用者的訪問,大多數網站都有相應的防爬蟲策略。一旦訪問行為被認定為爬蟲,網站將會採取一定的措施,限制你的訪問,比如提示你,訪問過於頻繁讓你輸入驗證碼,更嚴重者,會封掉你的ip,禁止你訪問該網站。本系統定向抓取網頁資料的時候,將不間斷的訪問網站內容,如果不採取偽裝措施,很容易被網站識別為爬蟲行為而遮蔽掉。 本系統採用以下方法來防止爬蟲被遮蔽:

(a)模擬不同瀏覽器行為實現思路及程式碼
原理:
從scrapy的介紹我們可以知道,scrapy有下載中介軟體,在這個中介軟體我們可以對請求跟響應進行自定義處理,類似於spring面向切面程式設計,像一個鉤子嵌入到程式的執行前後。核心就是對請求的屬性進行修改 首先主要是對下載中介軟體進行了擴充套件,首先在seetings.py上面增加中介軟體, 其次,擴充套件中介軟體,主要是寫一個useragent列表,將常用的瀏覽器請求頭儲存為一個列表.
再讓請求的標頭檔案隨機在列表中取一個agent值,然後到下載器進行下載。
綜上,每次發出請求的時候模擬使用不同的瀏覽器對目標網站進行訪問。
(b)使用代理ip進行爬取的實現思路及程式碼。 首先在seetings.py上面增加中介軟體,擴充套件下載元件請求的標頭檔案隨機從代理ip池中取出一個代理值然後到下載器進行下載。
1. 代理ip池的設計與開發流程如下:

a. 對免費代理ip網站進行抓取。
b. 對代理ip進行儲存並驗證
c. 驗證通過儲存進資料庫
d. 如果滿足ip最大數量,則停止爬去,一定時間後驗證資料的ip有效性,將失效的ip刪除 e. 直到資料庫ip小於0,繼續爬取ip,重複步驟a。
代理ip爬蟲執行截圖:

(c)爬蟲異常狀態元件的處理 爬蟲沒有被遮蔽執行時,訪問網站不是一直都是200請求成功,而是有各種各樣的狀態,像上述爬蟲被禁的時候,其實返回的狀態是302,防止遮蔽元件就是捕捉到302狀態加以實現的。同時異常狀態的處理有利於爬蟲的健壯性。 在settings中擴充套件中介軟體捕捉到異常的情況之後,將請求Request重新加入到待下載隊列當中流程如下:
d)資料儲存模組 資料儲存模組主要負責將slave端爬取解析的頁面進行儲存。使用Mongodb對資料進行儲存。 Scrapy支援資料儲存的格式有json,csv和xml等文字格式,使用者可以在執行爬蟲時設定,例如:scrapy crawl spider -o items.json -t json,也可以在Scrapy工程檔案額ItemPipline檔案中定義,同時,Scrapy也支援資料庫儲存,如Monogdb,Redis等,當資料量大到一定程度時,可以做Mongodb或者Reids的叢集來解決問題,本系統資料儲存如下圖所示:

(g)資料視覺化設計 資料的視覺化其實也就是,將資料庫的資料轉換成我們使用者容易觀察的形式,本系統使用Mongodb對資料進行儲存。對資料進行視覺化基於Django+Semantiui,效果如下圖所示:
四、系統部署
因為分散式部署所需環境都是類似的,如果一個伺服器部署程式都需要在配置下環境顯得很麻煩,這裡使用了docker映象對爬蟲程式進行部署,使用了Daocloud上的scrapy-env對程式進行了部署 。系統以58同城租房平臺為抓取目標,執行十小時之後,持續抓取網頁數量共計幾萬條房源資料。
原文釋出時間為:2018-09-22
本文來自雲棲社群合作伙伴“ OA==&mid=2650341439&idx=1&sn=e4eb1ce0f67c4a713e49de3e234858f6&chksm=878116ccb0f69fda63bfebf54da6c7b12a34b2224a08294e75f0b5ffdae15b8dd2ee18540a89&scene=0#rd" target="_blank" rel="nofollow,noindex">大資料探勘DT機器學習 ”,瞭解相關資訊可以關注“ 大資料探勘DT機器學習 ”。