社會(huì)化海量數(shù)據(jù)采集爬蟲(chóng)框架搭建
隨著B(niǎo)IG DATA大數(shù)據(jù)概念逐漸升溫,如何搭建一個(gè)能夠采集海量數(shù)據(jù)的架構(gòu)體系擺在大家眼前。如何能夠做到所見(jiàn)即所得的無(wú)阻攔式采集、如何快速把不規(guī)則頁(yè)面結(jié)構(gòu)化并存儲(chǔ)、如何滿足越來(lái)越多的數(shù)據(jù)采集還要在有限時(shí)間內(nèi)采集。這篇文章結(jié)合我們自身項(xiàng)目經(jīng)驗(yàn)談一下。
我們來(lái)看一下作為人是怎么獲取網(wǎng)頁(yè)數(shù)據(jù)的呢?
- 打開(kāi)瀏覽器,輸入網(wǎng)址url訪問(wèn)頁(yè)面內(nèi)容。
- 復(fù)制頁(yè)面內(nèi)容的標(biāo)題、作者、內(nèi)容。
- 存儲(chǔ)到文本文件或者excel。
從技術(shù)角度來(lái)說(shuō)整個(gè)過(guò)程主要為 網(wǎng)絡(luò)訪問(wèn)、扣取結(jié)構(gòu)化數(shù)據(jù)、存儲(chǔ)。我們看一下用java程序如何來(lái)實(shí)現(xiàn)這一過(guò)程。
- import java.io.IOException;
- import org.apache.commons.httpclient.HttpClient;
- import org.apache.commons.httpclient.HttpException;
- import org.apache.commons.httpclient.HttpStatus;
- import org.apache.commons.httpclient.methods.GetMethod;
- import org.apache.commons.lang.StringUtils;
- public class HttpCrawler {
- public static void main(String[] args) {
- String content = null ;
- try {
- HttpClient httpClient = new HttpClient();
- //1、網(wǎng)絡(luò)請(qǐng)求
- GetMethod method = new GetMethod("http://www.baidu.com" );
- int statusCode = httpClient.executeMethod(method);
- if (statusCode == HttpStatus. SC_OK) {
- content = method.getResponseBodyAsString();
- //結(jié)構(gòu)化扣取
- String title = StringUtils.substringBetween(content, "<title>" , "</title>" );
- //存儲(chǔ)
- System. out .println(title);
- }
- } catch (HttpException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- }
- }
- }
通過(guò)這個(gè)例子,我們看到通過(guò)httpclient獲取數(shù)據(jù),通過(guò)字符串操作扣取標(biāo)題內(nèi)容,然后通過(guò)system.out輸出內(nèi)容。大家是不是感覺(jué)做 一個(gè)爬蟲(chóng)也還是蠻簡(jiǎn)單呢。這是一個(gè)基本的入門(mén)例子,我們?cè)僭敿?xì)介紹怎么一步一步構(gòu)建一個(gè)分布式的適用于海量數(shù)據(jù)采集的爬蟲(chóng)框架。
整個(gè)框架應(yīng)該包含以下部分,資源管理、反監(jiān)控管理、抓取管理、監(jiān)控管理??匆幌抡麄€(gè)框架的架構(gòu)圖:
- 資源管理指網(wǎng)站分類體系、網(wǎng)站、網(wǎng)站訪問(wèn)url等基本資源的管理維護(hù);
- 反監(jiān)控管理指被訪問(wèn)網(wǎng)站(特別是社會(huì)化媒體)會(huì)禁止爬蟲(chóng)訪問(wèn),怎么讓他們不能監(jiān)控到我們的訪問(wèn)時(shí)爬蟲(chóng)軟件,這就是反監(jiān)控機(jī)制了
一個(gè)好的采集框架,不管我們的目標(biāo)數(shù)據(jù)在哪兒,只要用戶能夠看到都應(yīng)該能采集到。所見(jiàn)即所得的無(wú)阻攔式采集,無(wú)論是否需要登錄的數(shù)據(jù)都能夠順利采 集?,F(xiàn)在大部分社交網(wǎng)站都需要登錄,為了應(yīng)對(duì)登錄的網(wǎng)站要有模擬用戶登錄的爬蟲(chóng)系統(tǒng),才能正常獲取數(shù)據(jù)。不過(guò)社會(huì)化網(wǎng)站都希望自己形成一個(gè)閉環(huán),不愿意把 數(shù)據(jù)放到站外,這種系統(tǒng)也不會(huì)像新聞等內(nèi)容那么開(kāi)放的讓人獲取。這些社會(huì)化網(wǎng)站大部分會(huì)采取一些限制防止機(jī)器人爬蟲(chóng)系統(tǒng)爬取數(shù)據(jù),一般一個(gè)賬號(hào)爬取不了多 久就會(huì)被檢測(cè)出來(lái)被禁止訪問(wèn)了。那是不是我們就不能爬取這些網(wǎng)站的數(shù)據(jù)呢?肯定不是這樣的,只要社會(huì)化網(wǎng)站不關(guān)閉網(wǎng)頁(yè)訪問(wèn),正常人能夠訪問(wèn)的數(shù)據(jù),我們也 能訪問(wèn)。說(shuō)到底就是模擬人的正常行為操作,專業(yè)一點(diǎn)叫“反監(jiān)控”。
那一般網(wǎng)站會(huì)有什么限制呢?
一定時(shí)間內(nèi)單IP訪問(wèn)次數(shù),沒(méi)有哪個(gè)人會(huì)在一段持續(xù)時(shí)間內(nèi)過(guò)快訪問(wèn),除非是隨意的點(diǎn)著玩,持續(xù)時(shí)間也不會(huì)太長(zhǎng)??梢圆捎么罅坎灰?guī)則代理IP來(lái)模擬。
一定時(shí)間內(nèi)單賬號(hào)訪問(wèn)次數(shù),這個(gè)同上,正常人不會(huì)這么操作??梢圆捎么罅啃袨檎5馁~號(hào),行為正常就是普通人怎么在社交網(wǎng)站上操作,如果一個(gè)人一天24小時(shí)都在訪問(wèn)一個(gè)數(shù)據(jù)接口那就有可能是機(jī)器人了。
如果能把賬號(hào)和IP的訪問(wèn)策略控制好了,基本可以解決這個(gè)問(wèn)題了。當(dāng)然對(duì)方網(wǎng)站也會(huì)有運(yùn)維會(huì)調(diào)整策略,說(shuō)到底這是一個(gè)戰(zhàn)爭(zhēng),躲在電腦屏幕后的敵我雙 方,爬蟲(chóng)必須要能感知到對(duì)方的反監(jiān)控策略進(jìn)行了調(diào)整,通知管理員及時(shí)處理。未來(lái)比較理想應(yīng)該是通過(guò)機(jī)器學(xué)習(xí)算法自動(dòng)完成策略調(diào)整,保證抓取不間斷。
- 抓取管理指通過(guò)url,結(jié)合資源、反監(jiān)控抓取數(shù)據(jù)并存儲(chǔ);我們現(xiàn)在大部分爬蟲(chóng)系統(tǒng),很多都需要自己設(shè)定正則表 達(dá)式,或者使用htmlparser、jsoup等軟件來(lái)硬編碼解決結(jié)構(gòu)化抓取的問(wèn)題。不過(guò)大家在做爬蟲(chóng)也會(huì)發(fā)現(xiàn),如果爬取一個(gè)網(wǎng)站就去開(kāi)發(fā)一個(gè)類,在規(guī) 模小的時(shí)候還可以接受,如果需要抓取的網(wǎng)站成千上萬(wàn),那我們不是要開(kāi)發(fā)成百上千的類。為此我們開(kāi)發(fā)了一個(gè)通用的抓取類,可以通過(guò)參數(shù)驅(qū)動(dòng)內(nèi)部邏輯調(diào)度。比 如我們?cè)趨?shù)里指定抓取新浪微博,抓取機(jī)器就會(huì)調(diào)度新浪微博網(wǎng)頁(yè)扣取規(guī)則抓取節(jié)點(diǎn)數(shù)據(jù),調(diào)用存儲(chǔ)規(guī)則存儲(chǔ)數(shù)據(jù),不管什么類型***都調(diào)用同一個(gè)類來(lái)處理。對(duì) 于我們用戶只需要設(shè)置抓取規(guī)則,相應(yīng)的后續(xù)處理就交給抓取平臺(tái)了。
#p#
整個(gè)抓取使用了 xpath、正則表達(dá)式、消息中間件、多線程調(diào)度框架(參考)。xpath 是一種結(jié)構(gòu)化網(wǎng)頁(yè)元素選擇器,支持列表和單節(jié)點(diǎn)數(shù)據(jù)獲取,他的好處可以支持規(guī)整網(wǎng)頁(yè)數(shù)據(jù)抓取。我們使用的是google插件 XPath Helper,這個(gè)玩意可以支持在網(wǎng)頁(yè)點(diǎn)擊元素生成xpath,就省去了自己去查找xpath的功夫,也便于未來(lái)做到所點(diǎn)即所得的功能。正則表達(dá)式補(bǔ)充xpath抓取不到的數(shù)據(jù),還可以過(guò)濾一些特殊字符。消息中間件,起到抓取任務(wù)中間轉(zhuǎn)發(fā)的目的,避免抓取和各個(gè)需求方耦合。比如各個(gè)業(yè)務(wù)系統(tǒng)都可能抓取數(shù)據(jù),只需要向消息中間件發(fā)送一個(gè)抓取指令,抓取平臺(tái)抓完了會(huì)返回一條消息給消息中間件,業(yè)務(wù)系統(tǒng)在從消息中間件收到消息反饋,整個(gè)抓取完成。多線程調(diào)度框架之前提到過(guò),我們的抓取平臺(tái)不可能在同一時(shí)刻只抓一個(gè)消息的任務(wù);也不可能無(wú)限制抓取,這樣資源會(huì)耗盡,導(dǎo)致惡性循環(huán)。這就需要使用多線程調(diào)度框架來(lái)調(diào)度多線程任務(wù)并行抓取,并且任務(wù)的數(shù)量,保證資源的消耗正常。
不管怎么模擬總還是會(huì)有異常的,這就需要有個(gè)異常處理模塊,有些網(wǎng)站訪問(wèn)一段時(shí)間需要輸入驗(yàn)證碼,如果不處理后續(xù)永遠(yuǎn)返回不了正確數(shù)據(jù)。我們需要有機(jī)制能夠處理像驗(yàn)證碼這類異常,簡(jiǎn)單就是有驗(yàn)證碼了人為去輸入,高級(jí)一些可以破解驗(yàn)證碼識(shí)別算法實(shí)現(xiàn)自動(dòng)輸入驗(yàn)證碼的目的。
擴(kuò)展一下 :所見(jiàn)即所得我們是不是真的做到?規(guī)則配置也是個(gè)重復(fù)的大任務(wù)?重復(fù)網(wǎng)頁(yè)如何不抓???
1、有些網(wǎng)站利用js生成網(wǎng)頁(yè)內(nèi)容,直接查看源代碼是一堆js。 可以使用mozilla、webkit等可以解析瀏覽器的工具包解析js、ajax,不過(guò)速度會(huì)有點(diǎn)慢。
2、網(wǎng)頁(yè)里有一些css隱藏的文字。使用工具包把css隱藏文字去掉。
3、圖片flash信息。 如果是圖片中文字識(shí)別,這個(gè)比較好處理,能夠使用ocr識(shí)別文字就行,如果是flash目前只能存儲(chǔ)整個(gè)url。
4、一個(gè)網(wǎng)頁(yè)有多個(gè)網(wǎng)頁(yè)結(jié)構(gòu)。如果只有一套抓取規(guī)則肯定不行的,需要多個(gè)規(guī)則配合抓取。
5、html不完整,不完整就不能按照正常模式去扣取。這個(gè)時(shí)候用xpath肯定解析不了,我們可以先用htmlcleaner清洗網(wǎng)頁(yè)后再解析。
6、 如果網(wǎng)站多起來(lái),規(guī)則配置這個(gè)工作量也會(huì)非常大。如何幫助系統(tǒng)快速生成規(guī)則呢?首先可以配置規(guī)則可以通過(guò)可視化 配置,比如用戶在看到的網(wǎng)頁(yè)想對(duì)它抓取數(shù)據(jù),只需要拉開(kāi)插件點(diǎn)擊需要的地方,規(guī)則就自動(dòng)生成好了。另在量比較大的時(shí)候可視化還是不夠的,可以先將類型相同 的網(wǎng)站歸類,再通過(guò)抓取的一些內(nèi)容聚類,可以統(tǒng)計(jì)學(xué)、可視化抓取把內(nèi)容扣取出幾個(gè)版本給用戶去糾正,***確認(rèn)的規(guī)則就是新網(wǎng)站的規(guī)則。這些算法后續(xù)再講。 這塊再補(bǔ)充一下(多謝zicjin建議):
背景:如果我們需要抓取的網(wǎng)站很多,那如果靠可視化配置需要耗費(fèi)大量的人力,這是個(gè)成本。并且這個(gè)交給不懂html的業(yè)務(wù)去配置 準(zhǔn)確性值得考量,所以***還是需要技術(shù)做很多事情。那我們能否通過(guò)技術(shù)手段可以幫助生成規(guī)則減少人力成本,或者幫助不懂技術(shù)的業(yè)務(wù)準(zhǔn)確的把數(shù)據(jù)扣取下來(lái)并 大量復(fù)制。
方案:先對(duì)網(wǎng)站分類,比如分為新聞、論壇、視頻等,這一類網(wǎng)站的網(wǎng)頁(yè)結(jié)構(gòu)是類似的。在業(yè)務(wù)打開(kāi)需要扣取的還沒(méi)有錄入我們規(guī)則庫(kù)的 網(wǎng)頁(yè)時(shí),他先設(shè)定這個(gè)頁(yè)面的分類(當(dāng)然這個(gè)也可以機(jī)器預(yù)先判斷,他們來(lái)選擇,這一步必須要人判斷下),有了分類后,我們會(huì)通過(guò)“統(tǒng)計(jì)學(xué)、可視化判斷”識(shí)別 這一分類的字段規(guī)則,但是這個(gè)是機(jī)器識(shí)別的規(guī)則,可能不準(zhǔn)確,機(jī)器識(shí)別完后,還需要人在判斷一下。判斷完成后,***形成規(guī)則才是新網(wǎng)站的規(guī)則
7、對(duì)付重復(fù)的網(wǎng)頁(yè),如果重復(fù)抓取會(huì)浪費(fèi)資源,如果不抓需要一個(gè)海量的去重判斷緩存。判斷抓不抓,抓了后存不存,并且這個(gè)緩存需要快速讀寫(xiě)。常見(jiàn)的做法有bloomfilter、相似度聚合、分類海明距離判斷。
- 監(jiān)控管理指不管什么系統(tǒng)都可能出問(wèn)題,如果對(duì)方服務(wù)器宕機(jī)、網(wǎng)頁(yè)改版、更換地址等我們需要***時(shí)間知道,這時(shí)監(jiān)控系統(tǒng)就起到出現(xiàn)了問(wèn)題及時(shí)發(fā)現(xiàn)并通知聯(lián)系人。
目前這樣的框架搭建起來(lái)基本可以解決大量的抓取需求了。通過(guò)界面可以管理資源、反監(jiān)控規(guī)則、網(wǎng)頁(yè)扣取規(guī)則、消息中間件狀態(tài)、數(shù)據(jù)監(jiān)控圖表,并且可以 通過(guò)后臺(tái)調(diào)整資源分配并能動(dòng)態(tài)更新保證抓取不斷電。不過(guò)如果一個(gè)任務(wù)的處理特別大,可能需要抓取24個(gè)小時(shí)或者幾天。比如我們要抓取一條微博的轉(zhuǎn)發(fā),這個(gè) 轉(zhuǎn)發(fā)是30w,那如果每頁(yè)線性去抓取耗時(shí)肯定是非常慢了,如果能把這30w拆分很多小任務(wù),那我們的并行計(jì)算能力就會(huì)提高很多。不得不提的就是把大型的抓 取任務(wù)hadoop化,廢話不說(shuō)直接上圖:
今天先寫(xiě)到這里,后續(xù)再介紹下 日均千萬(wàn)大型采集項(xiàng)目實(shí)戰(zhàn)。