Nutch讀取詳細抓取內容-Segments的方法 – FetchedSegments

前言:這篇文章說明如何透過簡單的Java code去讀取Nutch所抓回來的segments資料,這議題在2006年網路上已經有人給了一個範例,然而這個範例過久,除非你是使用nutch 0.7以前的版本,他的API可能還會支援,但是nutch 0.7以後的版本,就完全無法以

FetchedSegments segments = new FetchedSegments(new LocalFileSystem(), segmentsDir.toString());建立FetchedSegments物件,也造成無法將nutch的結果完整的整合到自己的應用服務中,這是讓人很洩氣的。可惜的是,現今Nutch文件不多,中國那邊似乎不少這方面的文件,但沒講這麼深入,其中有看到透過nutch的指令去dump出segments的內容,基本上這樣的做法有點間接,但是像solr以及nutch的web套件,皆可以讀到所爬回來的內文(luke似乎沒有提供),因此我深信一定有方法,試了幾天,也就弄出來了,以下就是詳細的方法,此篇文章亦附有範例,若跑不起來的,應該是外面那幾個hadoop的xml設定問題,沒有hadoop的環境也無法跑這段code。

Nutch (http://nutch.apache.org/) 我就不多說了- Powerful、Scalable、Open Source的搜尋引擎系統,給他種子,他會幫你抓一堆網頁回來,抓多深,給參數,抓多廣,給種子,基本上去抓這件事情,好好的去設定Nutch就沒什麼問題了,但是,抓回來之後要怎麼分析?

抓下來後,在指定的位置,總共有五個資料夾,分別為:Crawldb、Linkdb、Segments、Indexes與Index。Nutch的文件索引是透過鼎鼎大名的Lucene來處理,然而,他不會把所有的內容都去做index,網頁內容就不會了。現在我打算要做個輿情系統,只有標題以及網址,對我來說過於概略,我需要內容,到底網頁抓回來的內容在哪裡?分別看這五個資料夾放了哪些東西?

  • Crawldb:所需抓取得超連結訊息(下載的URL、下載日期與頁面更新檢查時間)
  • Linkdb:存放所有的超連結及其每個連接的地址
  • Segments:存放抓取的頁面
  • Indexes:存放每次下載的獨立索引目錄,是由Crawldb、Linkdb和segments合成 (bin/nutch index crawl/indexs crawl/crawldb crawl/linkdb crawl/segments/*)
  • Index:由indexs合併而來,存放索引訊息。

沒有錯,就是在Segments這邊,Segments裡面放了完整的網頁內容,順帶一提,index裡面是經過lucene索引後的內容,要讀取index裡的內容,一點都不困難,只要用Lucene的IndexReader即可。

File nutchFileRoot = new File(“searchall/");

File index = new File(nutchFileRoot,"index");

IndexSearcher searcher = new IndexSearcher(index.getAbsolutePath());

然後就去把所有文件繞過一遍即可,如下:

for(int i=0;i<searcher.maxdoc></searcher.maxdoc>

      Document doc = searcher.doc(i);

}

要用Lucene Library須配合所使用nutch的版本,基本上不建議再去抓新的lucene library,直接在$NUTCH_HOME/lib/裡面就有。以我附上的範例為例(nutch 1.0),需要lucene-misc-2.4.0與lucene-core-2.4.0.jar這兩個。

由上述可知,要讀取index是件容易的事情,然而,要讀取內容就麻煩了些,我們需要用到Nutch所提供的類別,也就是這篇文章的主角-FetchedSegments。

要取得FetchedSegments的物件(instance),需要有兩個傳入參數,一個是Hadoop套件的Configuration,另一個則是Hadoop的Path。你可能會認為,一定要用到Hadoop嗎?沒有錯!!一定要在hadoop環境下,因為nutch從0.8之後,已經將核心的運算透過map-reduce去執行,即便你的資料室放在local file system (not hdfs),你還是需要有hadoop的運算平台。

那我們就建立Configuration物件吧,但是,現在不只是hadoop的問題了,還牽扯到nutch,因此要這樣去宣告:

Configuration nutchConf = NutchConfiguration.create();

我去看過create()的實作,裡面順帶做了兩件事情addResource(“nutch-default.xml");與addResource(“nutch-site.xml");因此請將你的nutch-default.xml與nutch-site.xml的設定放在Eclipse Project的最外層,或是你可以自己再指定這個路徑,此外,我順帶加了hadoop的環境,因此完整的code會長這樣。

Configuration nutchConf = NutchConfiguration.create();

nutchConf.addResource(“core-site.xml");

nutchConf.addResource(“hdfs-site.xml");

然後,另一個參數就是指定segments的位置,整個FetchedSegments會像這樣:

FetchedSegments segments = new FetchedSegments(nutchConf, new Path(“searchall/segments"));

好了,差不多到尾聲了,在Segments中,不論是成功或是失敗的crawl紀錄,都會記錄在Segments裡面,然而,去傾印它不是個好做法,因此,概念是這樣,你可以透過index裡面的欄位,去Segments裡面尋找相關的紀錄,要透過HitDetails這個類別將index與segments關聯起來,詳細的關聯方式是,將index所找出文件的屬性與值的map分別以字串陣列的方式代入HitDetails的物件,然後,FetchedSegments的物件會依照HitDetails的內容去找到合適的內容。以下是延續上面讀取index程式片段的完整內容。

       // iterate all documents from “index"

        for(int i=0;i<searcher.maxdoc></searcher.maxdoc>

         // get the ith document from index

         Document doc = searcher.doc(i);

         ArrayList<string> fields = new ArrayList<string>();</string></string>

         ArrayList<string> values = new ArrayList<string>();</string></string>

         Enumeration<field> e = doc.fields();</field>

         while (e.hasMoreElements()) {

             Field field = (Field)e.nextElement();

             fields.add(field.name());

             values.add(field.stringValue());

         }

         // important part!! associate the index and segments 

       HitDetails detail = new HitDetails((String[])fields.toArray(new String[fields.size()]),

                    (String[])values.toArray(new String[values.size()]));

        String aa = segments.getParseText(detail).toString();

         // the result we want!!

         System.out.println(aa);

    }

詳細的程式碼可從以下連結下載,因為內含nutch所爬回來台灣美食部落格的資料,因此60M上下。

http://www.chmao.idv.tw/NutchReader.zip

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s