陳春暉
(福建農(nóng)業(yè)職業(yè)技術(shù)學(xué)院,福建 福州 350000)
近年來(lái),互聯(lián)網(wǎng)數(shù)據(jù)的需求急劇增長(zhǎng),不僅是正在研發(fā)高性能爬蟲(chóng)技術(shù)的傳統(tǒng)搜索引擎公司,還有大數(shù)據(jù)、人工智能等新興企業(yè)和學(xué)術(shù)機(jī)構(gòu)有著巨大的需求,這就需要一種低成本的網(wǎng)絡(luò)爬蟲(chóng)器,以解決購(gòu)買(mǎi)數(shù)據(jù)的資金問(wèn)題[1-2]。 本文在對(duì)系統(tǒng)需求進(jìn)行分析的基礎(chǔ)上,提出了一種基于分布式爬蟲(chóng)的算法。
隨著異步負(fù)載技術(shù)的不斷發(fā)展,動(dòng)態(tài)頁(yè)面的異步負(fù)載在網(wǎng)絡(luò)產(chǎn)品中得到了越來(lái)越多的應(yīng)用。 當(dāng)前主要的爬蟲(chóng)無(wú)法對(duì)動(dòng)態(tài)頁(yè)面進(jìn)行有效分析,如何實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)的爬蟲(chóng)是本設(shè)計(jì)的主要內(nèi)容。
數(shù)據(jù)站點(diǎn)設(shè)計(jì)了一套防爬策略,以保護(hù)站點(diǎn)資料和普通使用者的存取,如當(dāng)前IP 訪問(wèn)被禁用、單位時(shí)間訪問(wèn)限制等。 所以,在設(shè)計(jì)系統(tǒng)時(shí),必須考慮如何處理好防爬蟲(chóng)問(wèn)題。
一個(gè)好的系統(tǒng),不僅要有很好的容錯(cuò)率,還要有很高的穩(wěn)定性。 實(shí)例證明,這種分布式爬蟲(chóng)系統(tǒng)必須具有良好的性能,可以在幾個(gè)星期甚至幾個(gè)月內(nèi)連續(xù)運(yùn)行。
在分布式網(wǎng)絡(luò)中,可擴(kuò)展性非常重要,因?yàn)榉植嫉木W(wǎng)絡(luò)爬蟲(chóng)程序會(huì)經(jīng)常添加或移除節(jié)點(diǎn),而Scrapy-Redis 分布體系結(jié)構(gòu)恰好能解決這個(gè)問(wèn)題,Scrapy-Redis 最大的優(yōu)勢(shì)在于可擴(kuò)充性,可以隨意添加和刪除任何一個(gè)節(jié)點(diǎn)。
本設(shè)計(jì)的爬蟲(chóng)系統(tǒng)期望在硬件成本最小的情況下獲得更高的性能,Scrapy-Redis 的分布架構(gòu)正是最佳的解決辦法,其所需的服務(wù)器數(shù)量很少,普通的計(jì)算機(jī)也能使用,即使是樹(shù)莓派(一種卡式的微型計(jì)算機(jī),造價(jià)約在200 RMB)也可以充當(dāng)Slave 節(jié)點(diǎn)。 而且,基于Scrapy-Redis 結(jié)構(gòu)的爬蟲(chóng)系統(tǒng)也是分布的,可以很好地實(shí)現(xiàn)對(duì)頁(yè)面的高效爬取[3]。
本文根據(jù)系統(tǒng)需求提出了基于分布式爬蟲(chóng)體系結(jié)構(gòu)的結(jié)構(gòu)模型,并將其劃分為數(shù)據(jù)層和業(yè)務(wù)邏輯兩個(gè)層次,結(jié)合現(xiàn)有的分布式框架進(jìn)行了詳細(xì)的設(shè)計(jì),如圖1 所示,實(shí)線箭頭表示數(shù)據(jù)流方向,虛線箭頭表示分布群集的Master 節(jié)點(diǎn)和Slave 節(jié)點(diǎn)間的“請(qǐng)求應(yīng)答”通信。
初始化參數(shù)模塊是為了讓系統(tǒng)能夠正常工作而初始化特定的參數(shù),在Slave 節(jié)點(diǎn)上,主節(jié)點(diǎn)IP 位址和要爬取的站點(diǎn)的參數(shù)都要初始化。 Slave 節(jié)點(diǎn)要在主節(jié)點(diǎn)上的IP 位址,并從Master 節(jié)點(diǎn)上的Redis 獲取爬取作業(yè),主節(jié)點(diǎn)無(wú)需事先知曉Slave 節(jié)點(diǎn)的IP 位址,而Slave節(jié)點(diǎn)可以隨時(shí)進(jìn)出。 此外,系統(tǒng)還會(huì)對(duì)網(wǎng)站的URL 初始化,該URL 將會(huì)出現(xiàn)在工作分配模組中的待執(zhí)行工作序列中。
2.2.1 任務(wù)分派
主要是對(duì)待完成的任務(wù)和已完成的任務(wù)進(jìn)行記錄,并根據(jù)已完成的任務(wù)排隊(duì)來(lái)防止對(duì)爬取的重復(fù)訪問(wèn)。
當(dāng)系統(tǒng)開(kāi)始時(shí),任務(wù)指派模塊會(huì)收到種子URL 的初始化,并將其放到要爬取的隊(duì)列中。
集群中Master 節(jié)點(diǎn)對(duì)Slave 節(jié)點(diǎn)采取優(yōu)先服務(wù)的原則,即從主節(jié)點(diǎn)的任務(wù)隊(duì)列中提取爬取任務(wù),提取完后記錄在已爬取任務(wù)隊(duì)列中[4]。
若某個(gè)Slave 節(jié)點(diǎn)表現(xiàn)得更好,那么該節(jié)點(diǎn)可以更快地獲得任務(wù);相反,則會(huì)變得更慢。 所以,這個(gè)策略可以最大限度地利用各個(gè)Slave 節(jié)點(diǎn)的最高性能,而這些Slave 節(jié)點(diǎn)本身是否在線,并不會(huì)對(duì)其他Slave 節(jié)點(diǎn)的處理任務(wù)造成任何影響。
2.2.2 爬蟲(chóng)策略模塊
不同的站點(diǎn)對(duì)數(shù)據(jù)的爬蟲(chóng)策略是不同的,一般采用廣度優(yōu)先策略和深度優(yōu)先策略獲取數(shù)據(jù)。
系統(tǒng)的穩(wěn)健性維護(hù)模塊包括4 個(gè)子模塊:心跳探測(cè)、IP 代理、類(lèi)人爬取模塊、記錄遺失任務(wù)模塊。
2.3.1 心跳探測(cè)模塊
模塊包括監(jiān)控進(jìn)程、狀態(tài)記錄、保護(hù)進(jìn)程等,是系統(tǒng)的一個(gè)關(guān)鍵部件,可以監(jiān)控每一個(gè)Slave 節(jié)點(diǎn)的登錄和訪問(wèn),包括當(dāng)前的狀態(tài)(比如:正常的爬蟲(chóng)、異常的要求、退出的情況)。
系統(tǒng)狀況監(jiān)控流程模塊:位于主節(jié)點(diǎn),作用是監(jiān)控當(dāng)前Slave 節(jié)點(diǎn)的狀態(tài),并對(duì)監(jiān)控結(jié)果進(jìn)行處理和記錄。
Slave 節(jié)點(diǎn)狀態(tài)記錄:將Slave 節(jié)點(diǎn)的狀態(tài)存入諸如 MySQL 之類(lèi)的關(guān)系數(shù)據(jù)庫(kù)中。
Slave 守護(hù)模塊:在Slave 的節(jié)點(diǎn)中,其功能是將自身的狀態(tài)在特定的時(shí)間段內(nèi)傳遞出去,并存儲(chǔ)在一個(gè)資料庫(kù)中。
Slave Device 模塊對(duì)Slave 節(jié)點(diǎn)的狀態(tài)記錄進(jìn)行計(jì)時(shí)寫(xiě)入,而Slave Development 通過(guò)該過(guò)程的狀態(tài)信息來(lái)判定該節(jié)點(diǎn)的狀態(tài)。
2.3.2 IP 代理模塊
是非常關(guān)鍵的模塊,能有效地防止網(wǎng)絡(luò)爬蟲(chóng),通過(guò)特定的策略,持續(xù)地修改IP 地址,使其造成多個(gè)站點(diǎn)的訪問(wèn),降低被攔截的概率。
IP 代理替換模塊:在Slave 節(jié)點(diǎn)上,主要作用是從IP 代理池中隨機(jī)提取IP,用于爬蟲(chóng)系統(tǒng)的爬蟲(chóng)和記錄IP 的異常情況。
2.3.3 類(lèi)人爬蟲(chóng)模塊
作為系統(tǒng)的關(guān)鍵部件,其作用是通過(guò)仿真用戶訪問(wèn)網(wǎng)站,欺騙網(wǎng)站的防爬機(jī)制,獲取用戶的數(shù)據(jù)。 本文提出了一種類(lèi)人爬取策略,主要內(nèi)容如下。
用戶代理策略:由一些常見(jiàn)的用戶代理組成用戶代理庫(kù),在用戶使用時(shí)隨機(jī)選擇一個(gè),并將其安裝到爬蟲(chóng)系統(tǒng)中。
Cookie 戰(zhàn)略:選擇是否使用Cookie,取決于目標(biāo)站點(diǎn)對(duì)數(shù)據(jù)的爬蟲(chóng)。
隨機(jī)時(shí)間爬蟲(chóng)策略:通過(guò)仿真用戶在特定時(shí)間周期內(nèi)的存取次數(shù)和存取時(shí)間,欺騙目標(biāo)站點(diǎn)的頻率和存取時(shí)間,從而判定該系統(tǒng)是不是爬蟲(chóng);針對(duì)特定區(qū)域的爬蟲(chóng)限制,隨機(jī)產(chǎn)生一定的時(shí)間間隔。
通常情況下,使用最佳策略進(jìn)行組合,而在實(shí)際的爬行前,先對(duì)網(wǎng)站的忍耐程度進(jìn)行檢測(cè)(即嚴(yán)格的抗爬行戰(zhàn)略)。
2.3.4 記錄遺失任務(wù)模塊
模塊位于主計(jì)算機(jī)上,用于記錄因異常退出Slave節(jié)點(diǎn)而導(dǎo)致的丟失任務(wù)。 若Slave 節(jié)點(diǎn)沒(méi)有完成爬取,此時(shí)出現(xiàn)異常的Slave 節(jié)點(diǎn),爬蟲(chóng)任務(wù)將不能被發(fā)送到Master 節(jié)點(diǎn)上,這就會(huì)導(dǎo)致任務(wù)丟失。 本模塊主要包括任務(wù)丟失和任務(wù)丟失的日志。
數(shù)據(jù)爬蟲(chóng)模塊是利用特定的策略從頁(yè)面中獲取相應(yīng)的URL,包括自定義的爬蟲(chóng)策略和動(dòng)態(tài)的網(wǎng)頁(yè)爬蟲(chóng)。
2.4.1 添加自定義爬取策略模塊
在實(shí)際的爬行過(guò)程中,通常只需要特定的類(lèi)別或特定區(qū)域的信息,廣度優(yōu)先,深度優(yōu)先。 而爬行的覆蓋區(qū)域太大,則無(wú)法快速準(zhǔn)確地獲取所需要的信息,這就需要一個(gè)特殊的爬行器策略為特定站點(diǎn)提供有吸引力的信息。 此外,對(duì)不同站點(diǎn)的蠕動(dòng)行為所能忍受的范圍也不盡相同。 為了應(yīng)對(duì)更多的爬蟲(chóng)數(shù)據(jù),在此將加入一些事先設(shè)置的戰(zhàn)略配置。
2.4.2 動(dòng)態(tài)、靜態(tài)的網(wǎng)頁(yè)爬蟲(chóng)模塊
主要針對(duì)動(dòng)態(tài)頁(yè)面和靜止頁(yè)面采用不同的爬蟲(chóng)策略,分析動(dòng)態(tài)頁(yè)面所需的時(shí)間一般要比靜態(tài)頁(yè)面多,區(qū)分動(dòng)態(tài)頁(yè)面和靜態(tài)頁(yè)面,可以提高爬蟲(chóng)效率。
在動(dòng)態(tài)網(wǎng)頁(yè)分析方面,根據(jù)鄔柏[5]的建議,向白名單中添加網(wǎng)址,新網(wǎng)址將依據(jù)查詢(xún)的白名單,決定是否使用動(dòng)態(tài)頁(yè)面的解析方式,并將不包含白名單但視為動(dòng)態(tài)頁(yè)面的URL。 在此基礎(chǔ)上,本設(shè)計(jì)采用了如下的改進(jìn)方法。
利用規(guī)則基礎(chǔ)來(lái)判定URL 對(duì)應(yīng)于存儲(chǔ)預(yù)先調(diào)查的目標(biāo)站點(diǎn)動(dòng)態(tài)頁(yè)面URL 的正則表達(dá)式的規(guī)則庫(kù),利用規(guī)則表達(dá)式,可以極大地減少規(guī)則庫(kù)的容量,減少系統(tǒng)的維護(hù)費(fèi)用。
對(duì)于異常解析的網(wǎng)站日志,由管理員進(jìn)行分析,然后確定是否進(jìn)行更新。 在相同的網(wǎng)站上,由于用戶關(guān)注的數(shù)據(jù),動(dòng)態(tài)頁(yè)面的分布規(guī)則是有限制的,通常不會(huì)因?yàn)橐?guī)則表達(dá)式的覆蓋而無(wú)法進(jìn)行動(dòng)態(tài)分析,大多數(shù)的異常都是由網(wǎng)絡(luò)異?;蛘叻琅老x(chóng)因子引起的。 所以,管理員在分析不正常的日志之后,就可以決定是否進(jìn)行規(guī)則的更新。
2.5.1 異常處理模塊
處理在執(zhí)行爬蟲(chóng)作業(yè)URL 時(shí)出現(xiàn)的異常,并將其傳回Master 節(jié)點(diǎn),由Master 節(jié)點(diǎn)進(jìn)行記錄。
2.5.2 數(shù)據(jù)分析模塊
根據(jù)預(yù)定的規(guī)則,對(duì)采集到的數(shù)據(jù)進(jìn)行分析,生成URL 或最終存儲(chǔ)的數(shù)據(jù)。 用戶依據(jù)網(wǎng)站、調(diào)查需求,從網(wǎng)站中提取或存儲(chǔ)的數(shù)據(jù)類(lèi)型(頁(yè)面文字格式、JSON格式、URL 的鏈接類(lèi)型)和URL 的規(guī)則,對(duì)相關(guān)的規(guī)則進(jìn)行配置。 在同一網(wǎng)站上,使用者要抽取的數(shù)據(jù)與URL 的鏈接是一樣的,符合一定規(guī)則的URL,就會(huì)相應(yīng)地抽取規(guī)則或者行為,例如,從某一列中抽取某一段話、某一段文字、點(diǎn)擊加載內(nèi)容等。
將Redis 在Master 端收到的數(shù)據(jù)(異常和爬蟲(chóng))進(jìn)行統(tǒng)一處理,包括:記錄、緩存、異常記錄、數(shù)據(jù)存儲(chǔ)等。
2.6.1 Slave 記錄數(shù)據(jù)模塊
模塊的作用是將Slave 的例外訪問(wèn)、數(shù)據(jù)處理系統(tǒng)中的數(shù)據(jù)處理、被Slave 節(jié)點(diǎn)獲取的工作、Slave 節(jié)點(diǎn)請(qǐng)求的下載量(包括請(qǐng)求例外)返回到主要節(jié)點(diǎn)的Redis中,并大量地傳送給關(guān)聯(lián)資料庫(kù)。
2.6.2 異常情況
保存異常數(shù)據(jù),主要是利用傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù),將異常爬蟲(chóng)記錄(在爬蟲(chóng)過(guò)程中出現(xiàn)的URL)保存下來(lái),以便管理員查詢(xún)異常,補(bǔ)充數(shù)據(jù)。
2.6.3 資料儲(chǔ)存
儲(chǔ)存爬取資料,采用傳統(tǒng)的關(guān)聯(lián)式資料庫(kù),存取主節(jié)點(diǎn)上的Redis 中儲(chǔ)存的資料,如最后儲(chǔ)存使用者所需要的資料,以備日后使用者查詢(xún)時(shí)所用。
本文在基于動(dòng)態(tài)網(wǎng)頁(yè)解析的網(wǎng)絡(luò)爬蟲(chóng)系統(tǒng)需求基礎(chǔ)上,對(duì)系統(tǒng)進(jìn)行了整體的設(shè)計(jì),并將其劃分為數(shù)據(jù)采集級(jí)和數(shù)據(jù)解析級(jí)、數(shù)據(jù)存儲(chǔ)層、節(jié)點(diǎn)接入層和系統(tǒng)管理層。 各層共包括存儲(chǔ)層、網(wǎng)頁(yè)下載和任務(wù)調(diào)度、網(wǎng)頁(yè)信息提取、網(wǎng)頁(yè)刪除、節(jié)點(diǎn)管理、爬蟲(chóng)管理6 大部分。隨著大數(shù)據(jù)時(shí)代的到來(lái),各種頁(yè)面的涌現(xiàn),傳統(tǒng)基于計(jì)算機(jī)的爬蟲(chóng)系統(tǒng)已不能很好地適應(yīng)目前的檢索需求,同時(shí)也需要更高的、實(shí)時(shí)的、精確的信息采集。 因此,如何有效地從網(wǎng)頁(yè)中抽取網(wǎng)頁(yè)信息,建立一個(gè)基于動(dòng)態(tài)網(wǎng)頁(yè)解析的網(wǎng)絡(luò)爬蟲(chóng)系統(tǒng)是十分必要的。