經(jīng)典面試題:如何設(shè)計(jì)一個(gè)網(wǎng)絡(luò)爬蟲(chóng)?
在本篇中,我們來(lái)設(shè)計(jì)一個(gè)網(wǎng)絡(luò)爬蟲(chóng):這是一個(gè)有趣且經(jīng)典的系統(tǒng)設(shè)計(jì)面試題。
網(wǎng)絡(luò)爬蟲(chóng)也被稱(chēng)為機(jī)器人或蜘蛛,它被搜索引擎用于發(fā)現(xiàn)網(wǎng)絡(luò)上的新內(nèi)容或更新內(nèi)容。內(nèi)容可以是網(wǎng)頁(yè)、圖片、視頻、PDF文件等。網(wǎng)絡(luò)爬蟲(chóng)開(kāi)始時(shí)會(huì)收集一些網(wǎng)頁(yè),然后跟隨這些網(wǎng)頁(yè)上的鏈接收集新的內(nèi)容。圖9-1展示了爬取過(guò)程的可視化示例。
爬蟲(chóng)的作用:
? 搜索引擎索引:這是最常見(jiàn)的用例。爬蟲(chóng)收集網(wǎng)頁(yè)以為搜索引擎創(chuàng)建本地索引。例如,Googlebot就是Google搜索引擎背后的網(wǎng)絡(luò)爬蟲(chóng)。
? 網(wǎng)絡(luò)歸檔:這是從網(wǎng)絡(luò)收集信息以保存數(shù)據(jù)供未來(lái)使用的過(guò)程。例如,許多國(guó)家的圖書(shū)館運(yùn)行爬蟲(chóng)來(lái)歸檔網(wǎng)站。比如美國(guó)國(guó)會(huì)圖書(shū)館 和歐盟網(wǎng)站歸檔 。
? 網(wǎng)絡(luò)挖掘:網(wǎng)絡(luò)的爆炸性增長(zhǎng)為數(shù)據(jù)挖掘提供了前所未有的機(jī)會(huì)。網(wǎng)絡(luò)挖掘有助于從互聯(lián)網(wǎng)中發(fā)現(xiàn)有用的知識(shí)。例如,頂級(jí)金融公司使用爬蟲(chóng)下載股東會(huì)議和年度報(bào)告,以了解公司的關(guān)鍵倡議。
? 網(wǎng)絡(luò)監(jiān)控:爬蟲(chóng)有助于在互聯(lián)網(wǎng)上監(jiān)控版權(quán)和商標(biāo)侵權(quán)。例如,Digimarc 使用爬蟲(chóng)來(lái)發(fā)現(xiàn)盜版作品并進(jìn)行報(bào)告。
開(kāi)發(fā)網(wǎng)絡(luò)爬蟲(chóng)的復(fù)雜度取決于我們打算支持的規(guī)模。它可能是一個(gè)只需幾個(gè)小時(shí)就能完成的小項(xiàng)目,或者是需要一個(gè)專(zhuān)業(yè)工程團(tuán)隊(duì)不斷改進(jìn)的巨大項(xiàng)目。因此,我們將在下面探討需要支持的規(guī)模和特性。
第一步 - 理解問(wèn)題并確定設(shè)計(jì)范圍
網(wǎng)絡(luò)爬蟲(chóng)的基本算法很簡(jiǎn)單:
1. 給定一組URL,下載由這些URL指向的所有網(wǎng)頁(yè)。
2. 從這些網(wǎng)頁(yè)中提取URL。
3. 將新的URL添加到待下載的URL列表中。重復(fù)這三個(gè)步驟。
網(wǎng)絡(luò)爬蟲(chóng)真的像這個(gè)基本算法那樣簡(jiǎn)單嗎?并非如此。設(shè)計(jì)一個(gè)可擴(kuò)展的可大規(guī)模網(wǎng)絡(luò)爬蟲(chóng)是一項(xiàng)極其復(fù)雜的任務(wù)。在面試時(shí)間內(nèi)設(shè)計(jì)一個(gè)大規(guī)模的網(wǎng)絡(luò)爬蟲(chóng)對(duì)任何人來(lái)說(shuō)都不太可能。在開(kāi)始設(shè)計(jì)之前,我們必須提問(wèn)以理解需求并確定設(shè)計(jì)范圍:
候選人:爬蟲(chóng)的主要目的是什么?它是用于搜索引擎索引、數(shù)據(jù)挖掘,還是其他什么?
面試官:搜索引擎索引。
候選人:網(wǎng)絡(luò)爬蟲(chóng)每月收集多少網(wǎng)頁(yè)?
面試官:10億個(gè)網(wǎng)頁(yè)。
候選人:包括哪些內(nèi)容類(lèi)型??jī)HHTML,還是也包括PDF和圖片等其他內(nèi)容類(lèi)型?
面試官:僅HTML。
候選人:我們應(yīng)該考慮新添加或編輯過(guò)的網(wǎng)頁(yè)嗎?
面試官:是的,我們應(yīng)該考慮新添加或編輯過(guò)的網(wǎng)頁(yè)。
候選人:我們需要存儲(chǔ)從網(wǎng)絡(luò)爬取的HTML頁(yè)面嗎?
面試官:是的,存儲(chǔ)時(shí)間長(zhǎng)達(dá)5年。
候選人:我們?nèi)绾翁幚砭哂兄貜?fù)內(nèi)容的網(wǎng)頁(yè)?
面試官:應(yīng)忽略具有重復(fù)內(nèi)容的頁(yè)面。
以上是我們向面試官提問(wèn)的一些樣本問(wèn)題。理解需求和澄清歧義非常重要。即使你被要求設(shè)計(jì)一個(gè)像網(wǎng)絡(luò)爬蟲(chóng)這樣的需求清晰的產(chǎn)品,你和你的面試官可能也會(huì)有不同的側(cè)重。
除了需要與面試官澄清的功能,還要注意記錄下一個(gè)好的網(wǎng)絡(luò)爬蟲(chóng)的以下特點(diǎn):
? 可擴(kuò)展性:網(wǎng)絡(luò)非常龐大。那里有數(shù)十億的網(wǎng)頁(yè)。網(wǎng)絡(luò)爬取應(yīng)該并行化并且極其高效。
? 穩(wěn)健性:網(wǎng)絡(luò)充滿了陷阱。糟糕的HTML、無(wú)響應(yīng)的服務(wù)器、崩潰、惡意鏈接等都很常見(jiàn)。爬蟲(chóng)必須處理所有的邊緣情況。
? 禮貌性:爬蟲(chóng)在短時(shí)間內(nèi)不應(yīng)向網(wǎng)站發(fā)送太多請(qǐng)求。
? 可擴(kuò)展性:系統(tǒng)應(yīng)該足夠靈活,以便在支持新的內(nèi)容類(lèi)型時(shí)只需要最小的改變。例如,如果我們將來(lái)想要爬取圖像文件,我們應(yīng)該不需要重新設(shè)計(jì)整個(gè)系統(tǒng)。
粗略估計(jì)
以下估計(jì)基于許多假設(shè),與面試官溝通以達(dá)成共識(shí)非常重要。
? 假設(shè)每個(gè)月下載10億個(gè)網(wǎng)頁(yè)。
? QPS:1,000,000,000 / 30天 / 24小時(shí) / 3600秒 = 每秒大約400個(gè)網(wǎng)頁(yè)。
? 峰值QPS = 2 * QPS = 800
? 假設(shè)平均網(wǎng)頁(yè)大小為500k。
? 10億頁(yè)面 x 500k = 每月需要500TB存儲(chǔ)。如果你對(duì)數(shù)字存儲(chǔ)單位不清楚,請(qǐng)回去復(fù)習(xí)“2的力量”那一篇。
? 假設(shè)數(shù)據(jù)存儲(chǔ)五年,500TB * 12個(gè)月 * 5年 = 30PB。存儲(chǔ)五年的內(nèi)容需要30PB的存儲(chǔ)空間。
第二步 - 提出高級(jí)設(shè)計(jì)并獲得認(rèn)同
一旦需求明確,我們就可以進(jìn)行高級(jí)設(shè)計(jì)。受到以往關(guān)于網(wǎng)絡(luò)爬蟲(chóng)的研究的啟發(fā),我們提出了如圖9-2所示的高級(jí)設(shè)計(jì)。
首先,我們探索每個(gè)設(shè)計(jì)組件以理解他們的功能。然后,我們逐步檢查爬蟲(chóng)的工作流程。
種子URL
網(wǎng)絡(luò)爬蟲(chóng)使用種子URL作為爬行過(guò)程的起點(diǎn)。例如,要從大學(xué)的網(wǎng)站上爬取所有網(wǎng)頁(yè),選擇種子URL的直觀方式是使用大學(xué)的域名。
要爬取整個(gè)網(wǎng)絡(luò),我們需要在選擇種子URL時(shí)富有創(chuàng)造性。一個(gè)好的種子URL作為一個(gè)好的起點(diǎn),爬蟲(chóng)可以利用它遍歷盡可能多的鏈接。通常的策略是將整個(gè)URL空間分割成更小的部分。首先提出的方法是基于區(qū)域性,因?yàn)椴煌膰?guó)家可能有不同的熱門(mén)網(wǎng)站。另一種方式是根據(jù)主題選擇種子URL;例如,我們可以將URL空間劃分為購(gòu)物、體育、健康保健等。種子URL的選擇是一個(gè)開(kāi)放性問(wèn)題。你不需要給出完美的答案。只需給面試官給出你的思考即可。
URL集合
大多數(shù)現(xiàn)代網(wǎng)絡(luò)爬蟲(chóng)將爬行狀態(tài)分為兩種:待下載和已下載。存儲(chǔ)待下載URL的組件稱(chēng)為URL集合。你可以將其視為先進(jìn)先出(FIFO)隊(duì)列。要獲取關(guān)于URL集合的詳細(xì)信息,請(qǐng)參考深入了解部分。
HTML下載器
HTML下載器從互聯(lián)網(wǎng)上下載網(wǎng)頁(yè)。這些URL由URL集合提供。
DNS解析器
要下載一個(gè)網(wǎng)頁(yè),必須將URL轉(zhuǎn)換為IP地址。HTML下載器調(diào)用DNS解析器,獲取URL對(duì)應(yīng)的IP地址。例如,URL http://www.wikipedia.org 被轉(zhuǎn)換為IP地址198.35.26.96。
內(nèi)容解析器
下載一個(gè)網(wǎng)頁(yè)后,必須對(duì)其進(jìn)行解析和驗(yàn)證,因?yàn)楦袷讲徽_的網(wǎng)頁(yè)可能會(huì)引發(fā)問(wèn)題并浪費(fèi)存儲(chǔ)空間。在爬蟲(chóng)服務(wù)器中實(shí)現(xiàn)內(nèi)容解析器會(huì)減慢爬行過(guò)程。因此,內(nèi)容解析器最好是一個(gè)獨(dú)立的組件。
內(nèi)容爬過(guò)了嗎?
在線研究顯示,29%的網(wǎng)頁(yè)是重復(fù)內(nèi)容,這可能導(dǎo)致相同的內(nèi)容被多次存儲(chǔ)。我們引入“內(nèi)容爬過(guò)了嗎?”數(shù)據(jù)結(jié)構(gòu)來(lái)消除數(shù)據(jù)冗余并縮短處理時(shí)間。它有助于檢測(cè)以前存儲(chǔ)在系統(tǒng)中的新內(nèi)容。比較兩個(gè)HTML文檔,我們可以逐字符地比較它們。然而,這種方法慢且耗時(shí),特別是當(dāng)涉及到數(shù)十億個(gè)網(wǎng)頁(yè)時(shí)。一種有效的方法是比較兩個(gè)網(wǎng)頁(yè)的哈希值。
內(nèi)容存儲(chǔ)
這是一個(gè)用于存儲(chǔ)HTML內(nèi)容的存儲(chǔ)系統(tǒng)。存儲(chǔ)系統(tǒng)的選擇取決于諸如數(shù)據(jù)類(lèi)型、數(shù)據(jù)大小、訪問(wèn)頻率、壽命等因素。使用的存儲(chǔ)介質(zhì)包括磁盤(pán)和內(nèi)存。
? 因?yàn)閿?shù)據(jù)集過(guò)大,無(wú)法全部放入內(nèi)存,所以大部分內(nèi)容存儲(chǔ)在磁盤(pán)上。
? 受歡迎的內(nèi)容保留在內(nèi)存中以減少延遲。
URL提取器
URL提取器從HTML頁(yè)面中解析并提取鏈接。圖9-3顯示了一個(gè)鏈接提取過(guò)程。通過(guò)添加“https://en.wikipedia.org”前綴,將相對(duì)路徑轉(zhuǎn)換為絕對(duì)URL。
URL過(guò)濾器
URL過(guò)濾器排除某些內(nèi)容類(lèi)型,文件擴(kuò)展名,錯(cuò)誤鏈接和“黑名單”網(wǎng)站中的URL。
URL爬過(guò)了嗎?
“URL爬過(guò)了嗎?”是一個(gè)跟蹤之前訪問(wèn)過(guò)的URL或已經(jīng)在前沿的URL的數(shù)據(jù)結(jié)構(gòu)?!癠RL爬過(guò)了嗎?”有助于避免多次添加同一URL,因?yàn)檫@可能會(huì)增加服務(wù)器負(fù)載并可能導(dǎo)致潛在的無(wú)限循環(huán)。
布隆過(guò)濾器和哈希表是實(shí)現(xiàn)“URL爬過(guò)了嗎?”組件的常見(jiàn)技術(shù)。我們?cè)谶@里不會(huì)詳細(xì)介紹布隆過(guò)濾器和哈希表的實(shí)現(xiàn)。
URL存儲(chǔ)
URL存儲(chǔ)存放已經(jīng)訪問(wèn)過(guò)的URL。
到目前為止,我們已經(jīng)討論了每個(gè)系統(tǒng)組件。接下來(lái),我們將它們組合在一起,以解釋工作流程。
網(wǎng)絡(luò)爬蟲(chóng)工作流程
為了更好地逐步解釋工作流程,我們?cè)谠O(shè)計(jì)圖中添加了序列號(hào),如圖9-4所示。
步驟1:將種子URL添加到URL集合。
步驟2:HTML下載器從URL集合獲取URL列表。
步驟3:HTML下載器從DNS解析器獲取URL的IP地址并開(kāi)始下載。
步驟4:內(nèi)容解析器解析HTML頁(yè)面并檢查頁(yè)面是否有誤。
步驟5:在內(nèi)容被解析和驗(yàn)證后,它被傳遞到“內(nèi)容已爬過(guò)?”組件。
步驟6:“內(nèi)容已爬過(guò)”組件檢查HTML頁(yè)面是否已經(jīng)在存儲(chǔ)中。
? 如果在存儲(chǔ)中,這意味著不同URL中的相同內(nèi)容已經(jīng)被處理過(guò)。在這種情況下,HTML頁(yè)面被丟棄。
? 如果不在存儲(chǔ)中,系統(tǒng)之前沒(méi)有處理過(guò)相同的內(nèi)容。內(nèi)容被傳遞到鏈接提取器。
步驟7:鏈接提取器從HTML頁(yè)面中提取鏈接。
步驟8:提取的鏈接被傳遞給URL過(guò)濾器。
步驟9:鏈接被過(guò)濾后,它們被傳遞給“URL已爬過(guò)?”組件。
步驟10:“URL已爬過(guò)”組件檢查URL是否已經(jīng)在存儲(chǔ)中,如果是,那么它已經(jīng)被處理過(guò),無(wú)需做任何事情。
步驟11:如果URL之前沒(méi)有被處理過(guò),那么它被添加到URL集合。
第三步 - 深入設(shè)計(jì)
到現(xiàn)在為止,我們已經(jīng)討論了高層設(shè)計(jì)。接下來(lái),我們將深入討論最重要的構(gòu)建組件和技術(shù):
? 深度優(yōu)先搜索(DFS)與廣度優(yōu)先搜索(BFS)
? URL集合
? HTML下載器
? 健壯性
? 可擴(kuò)展性
? 檢測(cè)并避免問(wèn)題內(nèi)容
DFS與BFS
你可以將網(wǎng)絡(luò)視為一個(gè)有向圖,其中網(wǎng)頁(yè)作為節(jié)點(diǎn),超鏈接(URL)作為邊。爬取過(guò)程可以被看作是從一個(gè)網(wǎng)頁(yè)到其他網(wǎng)頁(yè)的有向圖遍歷。兩種常見(jiàn)的圖遍歷算法是DFS和BFS。然而,DFS通常不是一個(gè)好的選擇,因?yàn)樵诰W(wǎng)絡(luò)爬蟲(chóng)的場(chǎng)景下DFS的深度可能非常深。
網(wǎng)絡(luò)爬蟲(chóng)常用的是BFS,它通過(guò)一個(gè)先進(jìn)先出(FIFO)隊(duì)列來(lái)實(shí)現(xiàn)。在一個(gè)FIFO隊(duì)列中,URL按照他們?nèi)腙?duì)的順序出隊(duì)。然而,這種實(shí)現(xiàn)有兩個(gè)問(wèn)題:
? 大多數(shù)來(lái)自同一網(wǎng)頁(yè)的鏈接都鏈接回同一host。在圖9-5中,wikipedia.com中的所有鏈接都是內(nèi)部鏈接,使得爬蟲(chóng)忙于處理來(lái)自同一主機(jī)(wikipedia.com)的URL。當(dāng)爬蟲(chóng)試圖并行下載網(wǎng)頁(yè)時(shí),維基百科的服務(wù)器將被請(qǐng)求淹沒(méi)。這被認(rèn)為是“不禮貌的”。
URL集合
URL集合有助于解決這些問(wèn)題。URL集合是一個(gè)存儲(chǔ)待下載URL的數(shù)據(jù)結(jié)構(gòu)。URL集合是確保禮貌、URL優(yōu)先級(jí)和新鮮度的重要組件。
禮貌
通常,網(wǎng)絡(luò)爬蟲(chóng)應(yīng)避免在短時(shí)間內(nèi)向同一主機(jī)服務(wù)器發(fā)送過(guò)多的請(qǐng)求。發(fā)送過(guò)多的請(qǐng)求被視為“不禮貌的”,甚至被視為拒絕服務(wù)(DOS)攻擊。例如,如果沒(méi)有任何限制,爬蟲(chóng)可以每秒向同一網(wǎng)站發(fā)送數(shù)千個(gè)請(qǐng)求。這可能會(huì)壓垮網(wǎng)絡(luò)服務(wù)器。
實(shí)施禮貌的一般思想是一次從同一主機(jī)下載一個(gè)頁(yè)面。并且在兩個(gè)下載任務(wù)之間添加延遲。禮貌約束是通過(guò)維護(hù)從網(wǎng)站主機(jī)名到下載(工作線程)的映射來(lái)實(shí)現(xiàn)的。每個(gè)下載線程都有一個(gè)獨(dú)立的FIFO隊(duì)列,并且只從該隊(duì)列下載URL。圖9-6顯示了管理禮貌的設(shè)計(jì)。
? 隊(duì)列路由器:確保每個(gè)隊(duì)列(b1,b2,... bn)只包含來(lái)自同一主機(jī)的URL。
? 映射表:將每個(gè)主機(jī)映射到一個(gè)隊(duì)列。
? FIFO隊(duì)列b1,b2至bn:每個(gè)隊(duì)列包含來(lái)自同一主機(jī)的URL。
? 隊(duì)列選擇器:每個(gè)工作線程映射到一個(gè)FIFO隊(duì)列,它只從該隊(duì)列下載URL。隊(duì)列選擇邏輯由隊(duì)列選擇器完成。
? 工作線程1到N。工作線程一次從同一主機(jī)下載一個(gè)網(wǎng)頁(yè)。可以在兩個(gè)下載任務(wù)之間添加延遲。
優(yōu)先級(jí)
論壇上的隨機(jī)帖子與首頁(yè)上的帖子具有不同的權(quán)重。盡管它們都包含“Apple”關(guān)鍵字,但爬蟲(chóng)優(yōu)先爬取Apple首頁(yè)是更成熟的做法。
我們根據(jù)有用性對(duì)URL進(jìn)行優(yōu)先級(jí)排序,這可以通過(guò)PageRank ,網(wǎng)站流量,更新頻率等來(lái)衡量。"優(yōu)先級(jí)處理器"是處理URL優(yōu)先級(jí)的組件。有關(guān)這個(gè)概念的深入信息,請(qǐng)參考參考資料。
圖9-7顯示了管理URL優(yōu)先級(jí)的設(shè)計(jì)。
? 優(yōu)先級(jí)處理器:它接受URL作為輸入并計(jì)算優(yōu)先級(jí)。
? 隊(duì)列f1至fn:每個(gè)隊(duì)列都有一個(gè)分配的優(yōu)先級(jí)。具有高優(yōu)先級(jí)的隊(duì)列具有更高的被選擇概率。
? 隊(duì)列選擇器:隨機(jī)選擇一個(gè)隊(duì)列,偏向于具有較高優(yōu)先級(jí)的隊(duì)列。
圖9-8展示了URL集合設(shè)計(jì),它包含兩個(gè)模塊:
? 前隊(duì)列:管理優(yōu)先級(jí)
? 后隊(duì)列:管理禮貌性
新鮮度
網(wǎng)頁(yè)一直處于不斷地添加、刪除和編輯的狀態(tài)。網(wǎng)絡(luò)爬蟲(chóng)必須定期重新爬取已下載的頁(yè)面,以保持我們的數(shù)據(jù)集新鮮。重新爬取所有的URL既耗時(shí)又資源密集。以下列出了一些優(yōu)化新鮮度的策略:
? 基于網(wǎng)頁(yè)的更新歷史進(jìn)行重新爬取。
? 對(duì)URL進(jìn)行優(yōu)先級(jí)排序,并更頻繁地重新爬取重要的頁(yè)面。
URL Frontier的存儲(chǔ)
在現(xiàn)實(shí)世界中為搜索引擎進(jìn)行爬取時(shí),集合中的URL數(shù)量可能達(dá)到幾億。把所有東西都放在內(nèi)存中既不持久也不可擴(kuò)展。但是磁盤(pán)速度慢,我們也不希望把所有東西都存儲(chǔ)在磁盤(pán)中;并且它很容易成為爬取的瓶頸。
我們采取了一種混合方法。大部分URL存儲(chǔ)在磁盤(pán)上,因此存儲(chǔ)空間不是問(wèn)題。為了減少?gòu)拇疟P(pán)讀取和寫(xiě)入磁盤(pán)的成本,我們?cè)趦?nèi)存中維護(hù)用于入隊(duì)/出隊(duì)操作的緩沖區(qū)。緩沖區(qū)中的數(shù)據(jù)會(huì)定期寫(xiě)入磁盤(pán)。
HTML下載器
HTML下載器使用HTTP協(xié)議從互聯(lián)網(wǎng)下載網(wǎng)頁(yè)。在討論HTML下載器之前,我們先看一下機(jī)器人排除協(xié)議。
Robots.txt
Robots.txt,也被稱(chēng)為機(jī)器人排除協(xié)議,是網(wǎng)站用來(lái)與爬蟲(chóng)交流的一種標(biāo)準(zhǔn)。它指定了爬蟲(chóng)允許下載的頁(yè)面。在嘗試爬取一個(gè)網(wǎng)站之前,爬蟲(chóng)應(yīng)該先檢查其對(duì)應(yīng)的robots.txt文件,并遵循其規(guī)則。
為了避免重復(fù)下載robots.txt文件,我們將文件的結(jié)果緩存在內(nèi)存中。該文件會(huì)定期下載并保存到緩存中。這是從https://www.amazon.com/robots.txt獲取的一部分robots.txt文件。像creatorhub這樣的目錄對(duì)于Google bot來(lái)說(shuō)是禁止訪問(wèn)的。
User-agent: Googlebot Disallow: /creatorhub/* Disallow: /rss/people//reviews Disallow: /gp/pdp/rss//reviews Disallow: /gp/cdp/member-reviews/ Disallow: /gp/aw/cr/
除了robots.txt,性能優(yōu)化是我們將要涉及到的HTML下載器的另一個(gè)重要概念。
性能優(yōu)化
以下是HTML下載器的性能優(yōu)化列表。
1. 分布式爬取
為了達(dá)到高性能,爬取工作分布在多個(gè)服務(wù)器上,并且每個(gè)服務(wù)器運(yùn)行多個(gè)線程。URL空間被劃分為更小的片段,因此,每個(gè)下載器負(fù)責(zé)URL的一個(gè)子集。圖9-9展示了分布式爬取的一個(gè)例子。
2. 緩存DNS解析器
由于許多DNS接口的同步性質(zhì),DNS請(qǐng)求可能需要一些時(shí)間,這使得DNS解析器成為爬蟲(chóng)的瓶頸。DNS響應(yīng)時(shí)間范圍從10ms到200ms。一旦一個(gè)爬蟲(chóng)線程進(jìn)行了對(duì)DNS的請(qǐng)求,其他線程就會(huì)被阻塞,直到第一個(gè)請(qǐng)求完成。為了避免頻繁調(diào)用DNS,維護(hù)我們自己的DNS緩存是一種有效的速度優(yōu)化技術(shù)。我們的DNS緩存保存域名到IP地址的映射,并由定時(shí)任務(wù)定期更新。
3. 區(qū)域性
地理分布爬取服務(wù)器。當(dāng)爬取服務(wù)器更接近網(wǎng)站主機(jī)時(shí),可以縮短下載時(shí)間。區(qū)域性設(shè)計(jì)適用于大多數(shù)系統(tǒng)組件:爬取服務(wù)器、緩存、隊(duì)列、存儲(chǔ)等。
4. 短超時(shí)
一些網(wǎng)頁(yè)服務(wù)器響應(yīng)慢或者可能根本不響應(yīng)。為了避免長(zhǎng)時(shí)間等待,我們?cè)O(shè)定了最大等待時(shí)間。如果一個(gè)主機(jī)在預(yù)定的時(shí)間內(nèi)沒(méi)有響應(yīng),爬蟲(chóng)將停止該任務(wù)并爬取其他頁(yè)面。
魯棒性
除了性能優(yōu)化外,魯棒性也是一個(gè)重要的考慮因素。我們提出了幾種提高系統(tǒng)魯棒性的方法:
? 一致性哈希:這有助于在下載器之間分配負(fù)載。新的下載服務(wù)器可以通過(guò)一致性哈希被添加或刪除。詳細(xì)信息請(qǐng)參前面的文章:設(shè)計(jì)一致性哈希。
? 保存爬取狀態(tài)和數(shù)據(jù):為了防止故障,爬取狀態(tài)和數(shù)據(jù)被寫(xiě)入到存儲(chǔ)系統(tǒng)。通過(guò)加載保存的狀態(tài)和數(shù)據(jù),可以輕松地重新啟動(dòng)中斷的爬取。
? 異常處理:在大規(guī)模系統(tǒng)中,錯(cuò)誤是不可避免且常見(jiàn)的。爬蟲(chóng)必須優(yōu)雅地處理異常,而不是讓系統(tǒng)崩潰。
? 數(shù)據(jù)驗(yàn)證:這是防止系統(tǒng)錯(cuò)誤的重要手段。
可擴(kuò)展性
幾乎每個(gè)系統(tǒng)都會(huì)發(fā)展,所以我們的一個(gè)設(shè)計(jì)目標(biāo)是使系統(tǒng)足夠靈活,以支持新的內(nèi)容類(lèi)型。爬蟲(chóng)可以通過(guò)插入新的模塊來(lái)擴(kuò)展。圖9-10顯示了如何添加新的模塊。
? PNG下載器模塊被插入以下載PNG文件。
? 添加了網(wǎng)頁(yè)監(jiān)視模塊,以監(jiān)控網(wǎng)絡(luò)并防止侵犯版權(quán)和商標(biāo)。
檢測(cè)并避免問(wèn)題內(nèi)容
本節(jié)討論了冗余、無(wú)意義或有害內(nèi)容的檢測(cè)和防止。
1. 冗余內(nèi)容
如前所述,近30%的網(wǎng)頁(yè)是重復(fù)的。哈?;蛐r?yàn)和有助于檢測(cè)重復(fù)內(nèi)容。
2. 蜘蛛陷阱
蜘蛛陷阱是一個(gè)會(huì)導(dǎo)致爬蟲(chóng)陷入無(wú)限循環(huán)的網(wǎng)頁(yè)。例如,一個(gè)無(wú)限深的目錄結(jié)構(gòu)如下所示: http://www.spidertrapexample.com/foo/bar/foo/bar/foo/bar/...
通過(guò)設(shè)置URL的最大長(zhǎng)度,可以避免這樣的蜘蛛陷阱。然而,沒(méi)有一種萬(wàn)全之策可以檢測(cè)蜘蛛陷阱。包含蜘蛛陷阱的網(wǎng)站很容易識(shí)別,因?yàn)樵谶@些網(wǎng)站上發(fā)現(xiàn)的網(wǎng)頁(yè)數(shù)量異常大。開(kāi)發(fā)自動(dòng)避免蜘蛛陷阱的算法很難;但是,用戶可以手動(dòng)驗(yàn)證并識(shí)別蜘蛛陷阱,并將這些網(wǎng)站從爬蟲(chóng)中排除或應(yīng)用一些自定義的URL過(guò)濾器。
3. 數(shù)據(jù)噪聲
有些內(nèi)容的價(jià)值很小或者沒(méi)有價(jià)值,如廣告、代碼片段、垃圾URL等。這些內(nèi)容對(duì)爬蟲(chóng)無(wú)用,如果可能,應(yīng)該被排除。
步驟4 - 總結(jié)
在本章中,我們首先討論了好的爬蟲(chóng)的特點(diǎn):可擴(kuò)展性、禮貌性、可擴(kuò)展性和魯棒性。然后,我們提出了一個(gè)設(shè)計(jì)并討論了關(guān)鍵組件。構(gòu)建一個(gè)可擴(kuò)展的網(wǎng)頁(yè)爬蟲(chóng)并非易事,因?yàn)榫W(wǎng)頁(yè)數(shù)量龐大且充滿陷阱。盡管我們已經(jīng)涵蓋了許多話題,但我們?nèi)匀贿z漏了許多相關(guān)的討論點(diǎn):
? 服務(wù)器端渲染:許多網(wǎng)站使用如JavaScript、AJAX等腳本在加載中生成鏈接。如果我們直接下載和解析網(wǎng)頁(yè),我們將無(wú)法獲取動(dòng)態(tài)生成的鏈接。為了解決這個(gè)問(wèn)題,我們?cè)诮馕鲰?yè)面之前首先進(jìn)行服務(wù)器端渲染(也稱(chēng)為動(dòng)態(tài)渲染)。
? 過(guò)濾掉不需要的頁(yè)面:由于存儲(chǔ)容量和爬取資源有限,反垃圾組件在過(guò)濾低質(zhì)量和垃圾頁(yè)面方面是很有用也是很有必有得。
? 數(shù)據(jù)庫(kù)復(fù)制和分片:使用復(fù)制和分片等技術(shù)來(lái)提高數(shù)據(jù)層的可用性、可擴(kuò)展性和可靠性。
? 水平擴(kuò)展:對(duì)于大規(guī)模爬取,需要數(shù)百甚至數(shù)千臺(tái)服務(wù)器來(lái)執(zhí)行下載任務(wù)。關(guān)鍵是保持服務(wù)器無(wú)狀態(tài)。
? 可用性、一致性和可靠性:這些概念是任何大型系統(tǒng)成功的核心。我們?cè)诘谇懊娴奈恼录?xì)討論了這些概念。忘了的話可以翻回去看看。
? 分析:收集和分析數(shù)據(jù)是任何系統(tǒng)的重要部分
往期推薦
