??? 作者:江南白衣

????Nutch是一個基于Lucene,類似Google的完整網(wǎng)絡(luò)搜索引擎解決方案,基于Hadoop的分布式處理模型保證了系統(tǒng)的性能,類似Eclipse的插件機制保證了系統(tǒng)的可客戶化,而且很容易集成到自己的應用之中。

??? Nutch 0.8 完全使用Hadoop重寫了骨干代碼,另有很多地方作了合理化修正,非常值得升級。

1.Nutch 0.8 的安裝與運行

nutch 0.7.2的中文安裝文檔滿街都是,nutch 0.8的安裝文檔見Tutorial (0.8) , 要注意兩點:

一是 crawl命令里的urls參數(shù)從指定文件變?yōu)榱酥付夸洠?即原來的urls 要改存到urls/foo 里。

二是 nutch-default.xml里http.agent.name屬性默認為空,必須在nutch-site.xml中為該屬性設(shè)值,否則會出錯。

注意nutch 爬行時的信息用log4j輸出在/logs 目錄下了,默認不再直接輸出到屏幕,除非你在配置文件里設(shè)fetcher.verbose為true。

Luke(http://www.getopt.org/luke) 是一個必備的索引閱讀工具。

另外,nutch需要在unix下奔跑,如果要裝在windows上,大家可以先裝個cygwin。(下載它的setup.exe 在線安裝很快裝完)。

最后,nutch 0.8的recawl 腳本也不同了。

2.Nutch?You should know?

2.1 一份文檔

nutch的文檔不多,而且多是安裝文檔,要深入nutch,就必須一字不漏的閱讀:

Introduction to Nutch, Part 1 Crawling? 和 Introduction to Nutch, Part 2 Searching

然后就是看源碼了,好在nutch的源碼非常均勻,簡短,沒有花哨的技巧,很容易把事情看明白。

2.2 三個目錄

首先理解nutch的三個數(shù)據(jù)目錄:

1.crawdb,linkdb 是web link目錄,存放url 及url的互聯(lián)關(guān)系,作為爬行與重新爬行的依據(jù),頁面默認30天過期。

2.segments 是主目錄,存放抓回來的網(wǎng)頁。頁面內(nèi)容有bytes[]的raw content 和 parsed text的形式。nutch以廣度優(yōu)先的原則來爬行,因此每爬完一輪會生成一個segment目錄。

3.index 是lucene的索引目錄,是indexs里所有index合并后的完整索引,注意索引文件只對頁面內(nèi)容進行索引,沒有進行存儲,因此查詢時要去訪問segments目錄才能獲得頁面內(nèi)容。

2.3?爬行過程

爬行過程在Introduction to Nutch, Part 1 Crawling?里已有詳細說明,或許直接看Crawl類來理解爬行的過程。

這里有一幅更直觀的圖:



Nutch用入口地址,地址正則表達式,搜索深度三種形式來限制。

因為使用了Hadoop(下篇再講),Nutch的代碼都按照Hadoop的模式來編寫以獲得分布式的能力,因此要先了解一下Hadoop,明白它Mapper,Reducer, InputFormat, OutputFormat類的作用才能更好的閱讀。

1.Fetcher類, 在run()里多線程運行FetcherThread,并調(diào)用恰當?shù)腜rotocol插件(支持http,ftp等協(xié)議)獲取內(nèi)容,調(diào)用恰當?shù)腜arser將內(nèi)容(html,pdf,excel)分析為文本,然后把內(nèi)容放到FetcherOutput類里,最后由FetcherOutputFormat類定義寫盤到segments的過程。

2.Indexer類,使用hadoop遍歷所有segments 目錄,將parseData文件序列化成ParseData類,從中獲得各種資料然后調(diào)用插件進行索引,最后仍然由ouputFormat類完成寫入索引的工作。

注意,如果你僅想使用Nutch的爬蟲,而不是其索引功能,可以仿照Indexer重寫自己的實現(xiàn),比如把segments內(nèi)容直接搬進數(shù)據(jù)庫。

3.Nutch 每條索引記錄的字段

url: 作為唯一標標識值,由BasicIndexingFilter類產(chǎn)生。

segment:由Indexer類產(chǎn)生。Nutch抓回來的頁面內(nèi)容放在segments目錄,lucene只會索引,不會store原文內(nèi)容,因此在查詢時要以segment與url作為外鍵,由FetchedSegments類根據(jù)hitsDetail從segments目錄獲得content。

boost:優(yōu)先級,由Indexer類調(diào)用插件計算產(chǎn)生。

title:顯示標題,在BasicIndexingFilter插件中被索引和存儲。

content: 主要的被搜索項,在BasicIndexingFilter插件中被索引。

2.4 搜索過程

Nutch提供了一個Fascade的NutchBean類供我們使用,一段典型的代碼如下

?
????NutchBean?bean?=?new?NutchBean();
????Query?query?
=?Query.parse(args[0]);
????Hits?hits?
=?bean.search(query,?NUM_HITS,"title",true);

????
for?(int?i?=?0;?i?<?hits.getLength();?i++)?{
??????Hit?hit?
=?hits.getHit(i);
??????HitDetails?details?
=?bean.getDetails(hit);

??????String?title?
=?details.getValue("title");
??????String?url?
=?details.getValue("url");
??????String?summary?
=bean.getSummary(details,?query);
????}
這里NutchBean為我們做了幾樣事情:

一是按Title field來排序。

二是支持分布式查詢,如果有配置servers,就會使用hadoop的IPC系統(tǒng),調(diào)用所有server上的nutchBeans,最后規(guī)約出總的結(jié)果。

三是每個站點像Google一樣只顯示分數(shù)最高的一頁,如果用戶還想看同站的其他結(jié)果,就需要進一步調(diào)用API訪問。

四是生成Summary,從segments目錄按segments和url 獲得content, 并按一定算法抽取出像Google一樣的包含關(guān)鍵字的文檔片斷。

3. 修改源碼或編寫插件

Nutch的源碼很容易修改和重新編譯,注意新編譯的class要壓回nutch-0.8.job(實際是一個jar)才能生效。

Nutch的插件機制及度類似Eclipse, 詳看http://wiki.apache.org/nutch/WritingPluginExample,只要實現(xiàn)某個插件接口,然后在plugins.xml里定義class,擴展點和依賴的jar,如

<plugin???id="index-basic"???version="1.0.0"???provider-name="nutch.org">
???<runtime>
??????<library?name
="index-basic.jar">
?????????<export?name
="*"/>
??????</library>
???</runtime>
???<requires>
??????<import?plugin
="nutch-extensionpoints"/>
???</requires>
???<extension?id
="org.apache.nutch.indexer.basic"
?????????????name
="Nutch?Basic?Indexing?Filter"?
?????????????point
="org.apache.nutch.indexer.IndexingFilter">
??????<implementation?id
="BasicIndexingFilter"??class="org.apache.nutch.indexer.basic.BasicIndexingFilter"/>
???</extension>
</plugin>


最后是八卦,Dedian同志翻譯的Doug Cutting 訪談錄 -- 關(guān)于搜索引擎的開發(fā)。
最最后,感謝創(chuàng)造 "C++ 必知必會" 這個短語的譯者:)