從這篇博客開始來具體的說搜索引擎的每一個核心模塊,先從爬蟲系統說起吧!
先來個大綱:
1、從爬蟲的設計角度看,優秀的爬蟲應該具備高性能,好的擴展性、健壯性和友好性。
2、從用戶體驗角度來說,對爬蟲的工作效果評價標準包括:抓取網頁的覆蓋率,抓取網頁的時新性和抓取網頁的重要性。
3、抓取策略,網頁更新策略,暗網抓取和分布式策略是爬蟲系統至關重要的四個方面內容,基本決定了爬蟲系統的質量和性能。
爬蟲的分類
1、批量型爬蟲
批量型爬蟲有比較明確的抓取范圍和目標,當爬蟲達到這個設定好的目標后,就會停止抓取過程。具體的目標可能會有差異,也許是設定抓取一定數量的網頁,也有可能是設定抓取的時間等。
2、增量型爬蟲
通用的商業搜索引擎基本都屬于增量型爬蟲,增量型爬蟲會保持持續不斷的抓取行為,對于抓取到的網頁,要定期更新。為啥要定期更新呢?因為互聯網網頁是動態的,不斷的進行變化,可能會新增網頁,可能網頁被刪除,也有可能原有的網頁內容被修改。
你應該有那么一次在使用百度搜索網頁的時候,點開某個鏈接,出現了404,這就說明百度對這個網頁的定期更新沒有做好,從而造成用戶體驗不好。不過對于海量的網頁進行定期更新,難度是很大的,所以出現這種現象是可以理解的。
3、垂直型爬蟲
垂直型爬蟲關注特定的主題內容或屬于某個行業的網頁,比如對于健康網站來說,只需要從互聯網上抓取和健康相關的網頁內容就可以,其他行業的內容不予以考慮。不過這種特殊的需求也造成了它的技術難點,怎么識別出網頁內容是否屬于指定行業或者主題。而且垂直型爬蟲最后需要的網頁內容肯定是互聯網中的一小部分網頁,為了節約系統的資源,不可能把互聯網上的所有網頁都下載下來以后再去做特定主題網頁的篩選,那么就需要爬蟲在抓取階段就能夠動態的識別某個網址是否與主題相關,并盡量不去抓取無關頁面,從而去節省資源。
通用搜索引擎的話,主要就是說增量型爬蟲了。
搜索引擎的通用爬蟲架構
1、在爬蟲開始抓取時,互聯網那么大,它不知道從何處開始抓取,所以需要給爬蟲一些起始url,比如那些流量非常大的網站,hao123這種,上面有好多優質網站的鏈接,讓爬蟲從hao123這些網站開始爬取,感覺比較靠譜哈!這些起始url也叫做種子url。
2、爬蟲中一個最重要的部分就是待抓取url隊列,因為它決定了爬蟲是否停止抓取,因為當隊列為空的時候,也就是沒有url可供爬蟲使用了,所以爬蟲抓取任務就完成了!
3、爬蟲從待抓取url隊列中獲得即將抓取的url,然后DNS域名解析得到網站主機的實際網絡地址,這個時候爬蟲就要用這個地址去進行正兒八經的抓取數據操作了,也就是下載網頁。
4、下載完網頁之后,要把這個網頁進行存儲,就是存儲到網頁庫中,然后還要把該網頁的url地址加入到已抓取url隊列中,這個隊列主要是為了防止同一個url的網頁重復下載,起到一個去重作用。
5、其實最重要的一步就是從剛剛下載的網頁中抽取出在該網頁中出現的所有url,然后把這些url加入到待抓取的url隊列中,以保證爬蟲下一次的抓取。
其實很好理解,我如果要認識世界上的所有人,那么一開始我會首先選擇一個社交能力很強,人緣好的人進行交往,在這里就是hao123,通過hao123我認識了一點資訊,百度,京東,淘寶網等好朋友,一點資訊這些大網站就是從hao123這個網頁中抽取出來的,下一步我就要通過一點資訊,百度等人來認識更多的人來擴大我的交際圈,那么此時就需要把一點資訊等url加入到待抓取url隊列中去完成這個任務,然后一直重復這個流程,直到你認識了所有人,當你認識了所有人之后,這個隊列就變空了,你的目標已經完成了!
再來扯點淡吧!說說爬蟲的特性,怎么才算是好的爬蟲?
1、高性能:互聯網太大了,網頁太多了,怎么才能在短時間下載完這些網頁?就是說下載要快。對于url隊列也要優化,網站那么多,url數量浩如煙海,需要設計高效的數據結構來實現隊列。
2、可擴展性:就是你的爬蟲系統對分布式是不是很友好,能不能實現動態添加機器和下架機器。目前實用的大型爬蟲系統一定是分布式運行的,就是有多臺機器專門做抓取,每臺服務器部署多個爬蟲,每個爬蟲多線程運行,通過多種方式增加并發性,上邊說的是所有抓取服務器在同一個數據中心的情況。甚至說大型的搜索引擎在全球有不同的數據中心,在歐洲的數據中心專門負責抓取英國,法國等國家的網頁,在亞洲的數據中心專門負責抓取中國,日本等國家的網頁,因為訪問本地的網頁比訪問遠程網頁速度快,所以不同地域數據中心分別抓取性能會更好。
3、健壯性:也就是你的爬蟲程序不會輕易崩潰,要能處理多種異常情況。
4、友好性:要保護被抓網站的部分私密性,也要減小被抓網站的壓力。你說你抓取人家的網站,本來就是有點厚臉皮的事情,你還把別人的后臺鏈接等私密性東西抓出來公之于眾,要不要點逼臉?人家的網站本來運行的好好的,你用那么多機器去訪問人家網站,不停的搞,不停的搞,最后形成DDOS分布式拒絕服務攻擊了,人家網站被你搞掛了,你心里能不能有點逼數?哈哈,來點粗口的更加容易理解!
保護網站的私密性,主要是靠道德來約束的,體現在網站有一個robots.txt文件,這個文件告訴所有搜索引擎,搜索引擎A可以抓取我的哪些內容,不能抓取哪些內容,搜索引擎B可以抓取我的哪些內容,不能抓取哪些內容。。。
就拿簡書來看一下吧,訪問http://www.lxweimin.com/robots.txt
User-agent是指定搜索引擎,*代表所有的搜索引擎。
Disallow代表禁止抓取的內容,一般是后臺目錄。
再來一個內容更加清晰的robots.txt
這些內容其實都是網站自己寫的,任何一個搜索引擎都可以無視這些內容,對網站進行肆意的抓取。不過在道德層面的話,做人,不,做搜索引擎也是要臉面的,所以一個友好的爬蟲要訪問被抓網站的robots.txt先看一下,訪問別人要有禮貌,看看網站主人對你的待客之道是什么?如果人家都不歡迎你,你還賴著,我靠,要不要臉面了?當然,你是的確可以賴著不走的,畢竟腿長在你自己身上!
抓取策略
1、廣度優先遍歷策略
我們大學學的數據結構中關于二叉樹的遍歷你是不是還記得?
分為廣度優先遍歷和深度優先遍歷,廣度優先就是把現在的幾個頁面都訪問完,然后再依次訪問這幾個頁面的子頁面(抽取出來的鏈接);而深度優先遍歷則是一個頁面干到底,訪問一個頁面,直接再訪問這個頁面的子頁面,然后訪問子頁面的子頁面,如此種種。。。
這個策略直接看圖已經很清楚了,不再解釋了。
2、非完全PageRank策略
這個方法是在PageRank上改的,因為PageRank方法需要所有的網頁數據才能進行計算,也就是要對網頁進行PageRank,那么就需要全網的網頁數據,顯然達不到這個要求,爬蟲的目的就是去爬取全網數據,如果得到全網數據了,還要爬蟲干雞毛。所以就產生了這種非完全的計算網頁鏈接關系排名的方法。
不可能每下載一個網頁就重新計算一下PageRank值,所以一般是攢夠K個網頁才重新計算排名,所以在下次重新計算排名之前,那么新抽取出來的網頁鏈接怎么辦,它們關于排名沒有任何數據???所以會給這些新網頁一個臨時PageRank值,具體就是將所有入鏈該網頁的PageRank值進行匯總充當它的臨時PageRank值。
全網的網頁是P1-P9,我們現在已經下載了P1-P3,待下載url隊列里邊是P4-P6,那么我們要用PageRank計算的就是在P4,P5,P6中,應該優先下載誰?主要是利用P1-P6的數據計算PageRank,P7-P9的數據不用,因為屬于未知的。計算后的結果是P5優先下載,然后把P5中的鏈接抽出來,就是P8了,此時賦予P8一個臨時的PageRank值,如果P8的值大于P4,P6,那么就優先下載P8。
這個算法主要是計算出網頁的排名從而確定下載的優先級,算法看起來很麻煩,而廣度優先遍歷就很簡單啊,簡單暴力,但是效果未必就比PageRank差??!
3、大站優先策略
這個就更好理解了,大網站肯定比小網站下載優先了!通過在url隊列中判斷url所對應網站的知名度來確定下載順序。效果比廣度優先遍歷好!
4、OCIP策略(Online Page Importance Computation)
在線頁面重要性計算,核心思想就是給互聯網的每一個網頁賦予一定的“金錢”,每當下載某個頁面P后,P就將自己的所有金錢p平均分給頁面中包含的鏈接頁面,然后把自己的金錢清空。在url待下載隊列中,通過比較每個url的金錢多少來進行排序,優先下載金錢多的網頁。效果還是很不錯的,比廣度優先遍歷好!
網頁更新策略
上面說了,我們主要是講增量型爬蟲,那么就需要對網頁的信息進行定期更新,從而保證搜索的質量。
1、歷史參考策略
過去頻繁更新的網頁,那么將來也會頻繁更新。
2、用戶體驗策略
注重用戶體驗,搜索的結果有好多頁,用戶一般傾向于只看前3頁,所以后面的內容不用更新的太著急,只要注重前3頁的更新就可以!
3、聚類抽樣策略
前兩種方法都是注重網頁的歷史數據,聚類是不需要歷史數據的,物以類聚嘛!我們只需要找到某一類網頁的特征,那么用這一類網頁中的代表性網頁更新行為來代表該網頁的行為就可以,如果代表性網頁頻繁更新,那么該網頁也頻繁更新!
暗網抓取
又看到一個新鮮的概念,比較好奇吧?暗網是什么?
暗網就是搜索引擎的爬蟲抓不到的網頁區域,而且這個區域很大很大,你平常能訪問到的區域(SurfaceWeb)跟暗網(DeepWeb)相比只是冰山一角,看一下百度暗網的結果多么可怕:
哈哈,別害怕,作為一個技術人,不要被這些表面性的東西所迷惑,要從技術上進行分析,為什么搜索引擎訪問不到暗網的這部分網頁資源。
我們看完了上面關于搜索引擎爬蟲抓取的原理,想必已經知道了搜索引擎爬蟲是依賴于網頁中的鏈接關系來發現新的頁面,只要爬蟲不停的爬取,不斷的抽取出鏈接,只要時間足夠長,按道理來說不會有漏網之魚的,因為一個網站總是要與其他網站有所聯系的,除非你真的是一個信息孤島!那么為什么暗網的區域還那么大,這么多的網頁資源無法進行抓取到,難道都是信息孤島嗎?當然不是,但是你要知道不是所有網站的網頁內容都是靜態的,有些網頁是靠用戶輸入然后查詢數據庫才顯示數據的!
舉個例子來說一下,就說12306吧,我們訪問它的主頁時,就得到下面的網頁,搜索引擎只能做到下載它的首頁。
但是如果我們現在要查詢車票呢?比如查詢從北京到上海的車票,顯示下面的網頁結果,這個網頁搜索引擎怎么去抓???因為這個網頁的產生是依賴我們手動輸入出發城市和目的地城市的,不同的輸入,結果就不同,這個不是靜態的網頁資源,搜索引擎的爬蟲無法抓取,所以就產生很大的暗網區域了!
現在的很多商業搜索引擎都在努力的進行暗網挖掘,把數據從數據庫中抓出來,增加信息的覆蓋程度。比如百度的阿拉丁計劃。
難點主要有:
1、對數據庫的查詢組合太多,比如12306,出發城市和目的地城市那么多,還有日期,一一組合的話,效率會很低。解決方法是用谷歌提出的富含信息查詢模板,就相當于你在12306查詢車票時候,只輸入出發城市,不輸入目的地城市,這個屬于一維模板,因為只填了一種信息。怎么評價這個模板是不是富含信息的呢?主要在出發城市這個屬性里,填入北京,上海各種城市,比較一下返回的信息是否差異性很大,這里顯然是差異性很大的,所以這個模板就是富含信息的模板,否則就不是富含信息的模板,利用富含信息的模板來抓取比較重要的內容。但是查詢模板本身可能數量也會很大,所以可以用Google的ISIT算法來減小提交查詢的數量。思想是從一維模板開始試探,如果是富含信息的模板,就轉到二維模板繼續試探,然后三維,四維......(存在的情況下),這樣可以找到絕大多數的富含信息的查詢模板。減少查詢次數,提高效率。
2、文本框問題,比如你要爬取的系統也是一個搜索引擎呢?比如你要抓取百度的數據庫,我靠,搜索引擎的數據庫可大啊,怎么才能把百度的數據庫內容都抓出來呢?我們知道訪問百度無非就是輸入搜索查詢詞就行了,那么我們需要一直輸入各種查詢詞來抓對應的數據,所以這個也很難!
對于這種帶文本輸入框的,我們需要讓爬蟲自動填寫文本框,但是爬蟲一開始也不知道自動填寫啥內容?。吭趺崔k?老辦法,還是人為的先給他來點種子,比如用小團圓,許三觀賣血記等種子來作為初始的輸入條件,下載查詢出來的頁面,然后從頁面抽取關鍵詞,比如抽取出了張愛玲,小說等關鍵詞,然后迭代查詢,并下載相應的頁面。
分布式爬蟲
最后來說一下爬蟲的分布式。
大型的分布式爬蟲分為三個等級:分布式數據中心、分布式抓取服務器、分布式爬蟲程序。
同一數據中心的抓取服務器之間的分布式架構有兩種:
主從式分布爬蟲
對等式分布爬蟲
主從式分布爬蟲
master/slave中的master是url服務器,主要負責維護url待下載隊列和對所有slave的url分發,還需要考慮分發任務的負載均衡問題。而slave就是負責具體的下載任務。所以整個爬蟲的系統瓶頸就在url服務器上。
對等式分布爬蟲
這種情況下,每個服務器之間的關系都是對等的,沒有url服務器了,每個服務器都要負責url隊列的維護工作和自己的下載任務,但是沒有了url服務器,就會出現問題,就是服務器的任務分工問題。
解決辦法是哈希取模,比如有3臺服務器,當接到www.google.com的網址時,計算網址的哈希值,并對3取模,發現取模后是1,那么就讓服務器1下載它。當有www.baidu.com網址出現時,哈希后取模得到2,那么就讓服務器2下載它。如此,就可以把任務大致均分到三個服務器上。
但是,如果需要對爬蟲系統進行擴展呢?比如加臺機器來增加抓取能力。因為現在只有3臺機器,所以取模時是按照3計算的,現在多了一臺,那么應該對4取模了,那么之前比如服務器2負責的抓取任務現在可能就不屬于它了,加了一臺機器完全把現有的系統抓取任務搞亂了。
一致性哈希算法
如下圖所示,對網址進行哈希,映射到0 - 2的32次方,大量的網址會被均勻的分布到各個位置,只需要讓每臺機器負責一個氛圍的網址進行下載就行了。當加機器時,只需要給它劃定范圍就行,不會對其他服務器的抓取url造成太大影響。當出現服務器宕機時,將會被轉發給宕機主機順時針下一個機器處理。