??? 作者:
江南白衣????
Nutch是一個(gè)基于
Lucene,類似Google的完整網(wǎng)絡(luò)搜索引擎解決方案,基于
Hadoop的分布式處理模型保證了系統(tǒng)的性能,類似Eclipse的插件機(jī)制保證了系統(tǒng)的可客戶化,而且很容易集成到自己的應(yīng)用之中。
??? Nutch 0.8 完全使用Hadoop重寫了骨干代碼,另有很多地方作了合理化修正,非常值得升級(jí)。
1.Nutch 0.8 的安裝與運(yùn)行
nutch 0.7.2的中文安裝文檔滿街都是,nutch 0.8的安裝文檔見Tutorial (0.8) , 要注意兩點(diǎn):
一是 crawl命令里的urls參數(shù)從指定文件變?yōu)榱酥付夸洠?即原來(lái)的urls 要改存到urls/foo 里。
二是 nutch-default.xml里http.agent.name屬性默認(rèn)為空,必須在nutch-site.xml中為該屬性設(shè)值,否則會(huì)出錯(cuò)。
注意nutch 爬行時(shí)的信息用log4j輸出在/logs 目錄下了,默認(rèn)不再直接輸出到屏幕,除非你在配置文件里設(shè)fetcher.verbose為true。
Luke(http://www.getopt.org/luke) 是一個(gè)必備的索引閱讀工具。
另外,nutch需要在unix下奔跑,如果要裝在windows上,大家可以先裝個(gè)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的源碼非常均勻,簡(jiǎn)短,沒有花哨的技巧,很容易把事情看明白。
2.2 三個(gè)目錄
首先理解nutch的三個(gè)數(shù)據(jù)目錄:
1.crawdb,linkdb 是web link目錄,存放url 及url的互聯(lián)關(guān)系,作為爬行與重新爬行的依據(jù),頁(yè)面默認(rèn)30天過(guò)期。
2.segments 是主目錄,存放抓回來(lái)的網(wǎng)頁(yè)。頁(yè)面內(nèi)容有bytes[]的raw content 和 parsed text的形式。nutch以廣度優(yōu)先的原則來(lái)爬行,因此每爬完一輪會(huì)生成一個(gè)segment目錄。
3.index 是lucene的索引目錄,是indexs里所有index合并后的完整索引,注意索引文件只對(duì)頁(yè)面內(nèi)容進(jìn)行索引,沒有進(jìn)行存儲(chǔ),因此查詢時(shí)要去訪問segments目錄才能獲得頁(yè)面內(nèi)容。
2.3?爬行過(guò)程
爬行過(guò)程在Introduction to Nutch, Part 1 Crawling?里已有詳細(xì)說(shuō)明,或許直接看Crawl類來(lái)理解爬行的過(guò)程。
這里有一幅更直觀的圖:

Nutch用入口地址,地址正則表達(dá)式,搜索深度三種形式來(lái)限制。
因?yàn)槭褂昧薍adoop(下篇再講),Nutch的代碼都按照Hadoop的模式來(lái)編寫以獲得分布式的能力,因此要先了解一下Hadoop,明白它Mapper,Reducer, InputFormat, OutputFormat類的作用才能更好的閱讀。
1.Fetcher類, 在run()里多線程運(yùn)行FetcherThread,并調(diào)用恰當(dāng)?shù)腜rotocol插件(支持http,ftp等協(xié)議)獲取內(nèi)容,調(diào)用恰當(dāng)?shù)腜arser將內(nèi)容(html,pdf,excel)分析為文本,然后把內(nèi)容放到FetcherOutput類里,最后由FetcherOutputFormat類定義寫盤到segments的過(guò)程。
2.Indexer類,使用hadoop遍歷所有segments 目錄,將parseData文件序列化成ParseData類,從中獲得各種資料然后調(diào)用插件進(jìn)行索引,最后仍然由ouputFormat類完成寫入索引的工作。
注意,如果你僅想使用Nutch的爬蟲,而不是其索引功能,可以仿照Indexer重寫自己的實(shí)現(xiàn),比如把segments內(nèi)容直接搬進(jìn)數(shù)據(jù)庫(kù)。
3.Nutch 每條索引記錄的字段
url: 作為唯一標(biāo)標(biāo)識(shí)值,由BasicIndexingFilter類產(chǎn)生。
segment:由Indexer類產(chǎn)生。Nutch抓回來(lái)的頁(yè)面內(nèi)容放在segments目錄,lucene只會(huì)索引,不會(huì)store原文內(nèi)容,因此在查詢時(shí)要以segment與url作為外鍵,由FetchedSegments類根據(jù)hitsDetail從segments目錄獲得content。
boost:優(yōu)先級(jí),由Indexer類調(diào)用插件計(jì)算產(chǎn)生。
title:顯示標(biāo)題,在BasicIndexingFilter插件中被索引和存儲(chǔ)。
content: 主要的被搜索項(xiàng),在BasicIndexingFilter插件中被索引。
2.4 搜索過(guò)程
Nutch提供了一個(gè)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來(lái)排序。
二是支持分布式查詢,如果有配置servers,就會(huì)使用hadoop的IPC系統(tǒng),調(diào)用所有server上的nutchBeans,最后規(guī)約出總的結(jié)果。
三是每個(gè)站點(diǎn)像Google一樣只顯示分?jǐn)?shù)最高的一頁(yè),如果用戶還想看同站的其他結(jié)果,就需要進(jìn)一步調(diào)用API訪問。
四是生成Summary,從segments目錄按segments和url 獲得content, 并按一定算法抽取出像Google一樣的包含關(guān)鍵字的文檔片斷。
3. 修改源碼或編寫插件
Nutch的源碼很容易修改和重新編譯,注意新編譯的class要壓回nutch-0.8.job(實(shí)際是一個(gè)jar)才能生效。
Nutch的插件機(jī)制及度類似Eclipse, 詳看http://wiki.apache.org/nutch/WritingPluginExample,只要實(shí)現(xiàn)某個(gè)插件接口,然后在plugins.xml里定義class,擴(kuò)展點(diǎn)和依賴的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++ 必知必會(huì)" 這個(gè)短語(yǔ)的譯者:)