簡介
Nutch 是一個開源Java 實現的搜尋引擎。它提供了我們運行自己的搜尋引擎所需的全部工具。包括全文搜尋和Web爬蟲。
儘管Web搜尋是漫遊Internet的基本要求, 但是現有web搜尋引擎的數目卻在下降. 並且這很有可能進一步演變成為一個公司壟斷了幾乎所有的web搜尋為其謀取商業利益.這顯然 不利於廣大Internet用戶.
Nutch為我們提供了這樣一個不同的選擇. 相對於那些商用的搜尋引擎, Nutch作為開放原始碼 搜尋引擎將會更加透明, 從而更值得大家信賴. 現在所有主要的搜尋引擎都採用私有的排序算法, 而不會解釋為什麼一個網頁會排在一個特定的位置. 除此之外, 有的搜尋引擎依照網站所付的 費用, 而不是根據它們本身的價值進行排序. 與它們不同, Nutch沒有什麼需要隱瞞, 也沒有 動機去扭曲搜尋的結果. Nutch將儘自己最大的努力為用戶提供最好的搜尋結果.
Nutch目前最新的版本為version v2.3。
目標
Nutch 致力於讓每個人能很容易, 同時花費很少就可以配置世界一流的Web搜尋引擎. 為了完成這一宏偉的目標, Nutch必須能夠做到:
* 每個月取幾十億網頁
* 為這些網頁維護一個索引
* 對索引檔案進行每秒上千次的搜尋
* 提供高質量的搜尋結果
組成
爬蟲crawler和查詢searcher。Crawler主要用於從網路上抓取網頁並為這些網頁建立索引。Searcher主要利用這些索引檢索用戶的查找關鍵字來產生查找結果。兩者之間的接口是索引,所以除去索引部分,兩者之間的耦合度很低。
Crawler和Searcher兩部分儘量分開的目的主要是為了使兩部分可以分散式配置在硬體平台上,例如將Crawler和Searcher分別放在兩個主機上,這樣可以提升性能。
爬蟲
Crawler的重點在兩個方面,Crawler的工作流程和涉及的數據檔案的格式和含義。數據檔案主要包括三類,分別是web database,一系列的segment加上index,三者的物理檔案分別存儲在爬行結果目錄下的db目錄下webdb子資料夾內,segments資料夾和index資料夾。那么三者分別存儲的信息是什麼呢?
一次爬行會產生很多個segment,每個segment記憶體儲的是爬蟲Crawler在單獨一次抓取循環中抓到的網頁以及這些網頁的索引。Crawler爬行時會根據WebDB中的link關係按照一定的爬行策略生成每次抓取循環所需的fetchlist,然後Fetcher通過fetchlist中的URLs抓取這些網頁並索引,然後將其存入segment。Segment是有時限的,當這些網頁被Crawler重新抓取後,先前抓取產生的segment就作廢了。在存儲中。Segment資料夾是以產生時間命名的,方便我們刪除作廢的segments以節省存儲空間。
Index是Crawler抓取的所有網頁的索引,它是通過對所有單個segment中的索引進行合併處理所得的。Nutch利用Lucene技術進行索引,所以Lucene中對索引進行操作的接口對Nutch中的index同樣有效。但是需要注意的是,Lucene中的segment和Nutch中的不同,Lucene中的segment是索引index的一部分,但是Nutch中的segment只是WebDB中各個部分網頁的內容和索引,最後通過其生成的index跟這些segment已經毫無關係了。
Web database,也叫WebDB,其中存儲的是爬蟲所抓取網頁之間的連結結構信息,它只在爬蟲Crawler工作中使用而和Searcher的工作沒有任何關係。WebDB記憶體儲了兩種實體的信息:page和link。Page實體通過描述網路上一個網頁的特徵信息來表征一個實際的網頁,因為網頁有很多個需要描述,WebDB中通過網頁的URL和網頁內容的MD5兩種索引方法對這些網頁實體進行了索引。Page實體描述的網頁特徵主要包括網頁內的link數目,抓取此網頁的時間等相關抓取信息,對此網頁的重要度評分等。同樣的,Link實體描述的是兩個page實體之間的連結關係。WebDB構成了一個所抓取網頁的連結結構圖,這個圖中Page實體是圖的結點,而Link實體則代表圖的邊。
工作流程
在創建一個WebDB之後(步驟1), “產生/抓取/更新”循環(步驟3-6)根據一些種子URLs開始啟動。當這個循環徹底結束,Crawler根據抓取中生成的segments創建索引(步驟7-10)。在進行重複URLs清除(步驟9)之前,每個segment的索引都是獨立的(步驟8)。最終,各個獨立的segment索引被合併為一個最終的索引index(步驟10)。
其中有一個細節問題,Dedup操作主要用於清除segment索引中的重複URLs,但是我們知道,在WebDB中是不允許重複的URL存在的,那么為什麼這裡還要進行清除呢?原因在於抓取的更新。比方說一個月之前你抓取過這些網頁,一個月後為了更新進行了重新抓取,那么舊的segment在沒有刪除之前仍然起作用,這個時候就需要在新舊segment之間進行除重。
Nutch和Lucene
Nutch是基於Lucene的。Lucene為Nutch提供了文本索引和搜尋的API。
一個常見的問題是:我應該使用Lucene還是Nutch?
最簡單的回答是:如果你不需要抓取數據的話,應該使用Lucene。
常見的套用場合是:你有數據源,需要為這些數據提供一個搜尋頁面。在這種情況下,最好的方式是直接從資料庫中取出數據並用Lucene API 建立索引。
在你沒有本地數據源,或者數據源非常分散的情況下,應該使用Nutch。
在分析了Crawler工作中設計的檔案之後,接下來我們研究Crawler的抓取流程以及這些檔案在抓取中扮演的角色。Crawler的工作原理:首先Crawler根據WebDB生成一個待抓取網頁的URL集合叫做Fetchlist,接著下載執行緒Fetcher根據Fetchlist將網頁抓取回來,如果下載執行緒有很多個,那么就生成很多個Fetchlist,也就是一個Fetcher對應一個Fetchlist。然後Crawler用抓取回來的網頁更新WebDB,根據更新後的WebDB生成新的Fetchlist,裡面是未抓取的或者新發現的URLs,然後下一輪抓取循環重新開始。這個循環過程可以叫做“產生/抓取/更新”循環。
指向同一個主機上Web資源的URLs通常被分配到同一個Fetchlist中,這可防止過多的Fetchers對一個主機同時進行抓取造成主機負擔過重。另外Nutch遵守Robots Exclusion Protocol,網站可以通過自定義Robots.txt控制Crawler的抓取。
在Nutch中,Crawler操作的實現是通過一系列子操作的實現來完成的。這些子操作Nutch都提供了子命令行可以單獨進行調用。下面就是這些子操作的功能描述以及命令行,命令行在括弧中。
1. 創建一個新的WebDb (admin db -create).
2. 將抓取起始URLs寫入WebDB中 (inject).
3. 根據WebDB生成fetchlist並寫入相應的segment(generate).
4. 根據fetchlist中的URL抓取網頁 (fetch).
5. 根據抓取網頁更新WebDb (updatedb).
6. 循環進行3-5步直至預先設定的抓取深度。
7. 根據WebDB得到的網頁評分和links更新segments (updatesegs).
8. 對所抓取的網頁進行索引(index).
9. 在索引中丟棄有重複內容的網頁和重複的URLs (dedup).
10. 將segments中的索引進行合併生成用於檢索的最終index(merge).