轉載:http://blog.ifeng.com/article/121656.html
互連網是一個龐大的非結構化的資料庫,將資料有效檢索並組織呈現出來有著巨大的應用前景,尤其是類似RSS的以XML為基礎的結構化的資料越來越多,內容的組織方式越來越靈活,檢索組織並呈現會有著越來越廣泛的應用範圍,同時在時效性和可讀性上也會有越來越高的要求。這一切的基礎是爬蟲,資訊的來源入口。一個高效,靈活可擴充的爬蟲對以上應用都有著無可替代的重要意義。
要設計一個爬蟲,首先需要考慮的效率。對於網路而言,基於TCP/IP的通訊編程有幾種方法。
第一種是單線程阻塞,這是最簡單也最容易實現的一種,一個例子:在Shell中通過curl,pcregrep等一系統命令可以直接實現一個簡單的爬蟲,但同時它的效率問題也顯而易見:由於是阻塞方式讀取,dns解析,建立串連,寫入請求,讀取結果這些步驟上都會產生時間的延遲,從而無法有效利用服務器的全部資源。
第二種是多線程阻塞。建立多個阻塞的線程,分別請求不同的url。相對於第一種方法,它可以更有效利用機器的資源,特別是網路資源,因為無數線程在同時工作,所以網路會比較充分的利用,但同時對機器CPU資源的消耗也是比較大,在使用者級多線程間的頻繁切換對於效能的影響已經值得我們考慮。
第三種是單線程非阻塞。這是目前使用的比較多的一種做法,無論在client還是server都有著廣泛的應用。在一個線程內開啟多個非阻塞的串連,通過poll/epoll/select對串連狀態進行判斷,在第一時間響應請求,不但充分利用了網路資源,同時也將本機CPU資源的消耗降至最低。這種方法需要對dns請求,串連,讀寫操作都採用非同步非阻塞操作,其中第一種比較複雜,可以採用adns作為解決方案,後面三個操作相對簡單可以直接在程式內實現。
效率問題解決後就需要考慮具體的設計問題了。
url肯定需要一個單獨的類進行處理,包括顯示,分析url,得到主機,連接埠,檔案資料。
然後需要對url進行排重,需要一個比較大的url Hash表。
如果還要對網頁內容進行排重,則還需要一個Document Hash表。
爬過的url需要記錄下來,由於量比較大,我們將它寫到磁碟上,所以還需要一個FIFO的類(記作urlsDisk)。
現在需要爬的url同樣需要一個FIFO類來處理,重新開始時,url會從定時從爬過的url FIFO裡取出來,寫到這個FIFO裡。正在啟動並執行爬蟲需要從這個FIFO裡讀資料出來,加入到主機類的url列表裡。當然,也會從前一個FIFO裡直接讀url出來,不過優先順序應該比這個裡面出來的url低,畢竟是已經爬過的。
爬蟲一般是對多個網站進行爬取,但在同時網站內dns的請求可以只做一次,這就需要將主機名稱獨立於url,單專屬一個類進行處理。
主機名稱解析完成後需要有一個解析完成的IP類與之應用,用於connect的時候使用。
HTML文檔的解析類也要有一個,用來分析網頁,取出裡面的url,加入到urlsDisk。
再加上一些字串,調度類,一個簡單的爬蟲基本上就完成了。
以上基本上是Larbin的設計思路,Larbin在具體實現上還有一些特殊的處理,例如帶了一個webserver,以及對特殊檔案的處理。Larbin有一點設計不不太好,就是慢的訪問會越來越多,佔用大量的串連,需要改進,另外如果對於大規模的爬蟲,這僅僅實現了抓取的部分,要分布式的擴充還需要增加url的集中管理與調度以及前台spider的分布式演算法。