1. 程式人生 > >nutch2二次開發筆記

nutch2二次開發筆記

1.Nutch介紹

    Nutch 是一個開源Java 實現的爬蟲框架和搜尋引擎。支援分散式處理,有兩個主版本1.x和2.x,它們的主要區別是1.x版本底層儲存使用的是HDFS,2.x引入了Gora作為儲存抽象層,從而支援各種NoSQL資料庫,如HBase,Cassandra等,另外也支援mysql

2.Nutch安裝問題

      具體的安裝步驟可以參考http://blog.csdn.net/lzjzy520/article/details/41596893,這裡僅補充自身遇到的幾個問題.

      一.2.3.1版本ant編譯時候, 會卡在 loading settings :: file = /usr/java/apache-nutch-2.3.1/ivy/ivysettings.xml,等待很久沒反應, 因此選擇了安裝2.2.1版本

      二.ant編譯過程較久,我第一次編譯成功花了40多分鐘,所以得耐心等待

      三.我是在不修改maven倉庫地址的情況下編譯成功,倉庫地址修改為http://mirrors.ibiblio.org/maven2/或者http://maven.oschina.net/content/groups/public/時編譯失敗,如果jar包下載不了,可以試試來回切換倉庫地址或者使用阿里雲的maven倉庫地址

      四.linux環境下安裝,nutch版本使用2.2.1,solr版本使用4.4.0,hbase版本使用0.90.4

3.Nutch的二次開發

        一.新增cookie抓取需要登入的網站

               首先,將nutch原始碼匯入到eclipse. nutch安裝目錄下列稱為NUTCH_HOME,另外,以儘量少改動原始碼和寫自定義外掛的前提下開發

            NUTCH_HOME/runtime/local/conf/nutch-site.xml檔案,新增

	<property>
	  <name>plugin.includes</name>
	  <value>protocol-http|protocol-httpclient|urlfilter-regex|parse-(html|tika|metatags)|filter-xpath|index-(basic|metadata|anchor|more)|scoring-opic|urlnormalizer-(pass|regex|basic)|language-identifier</value>
	  <description>Regular expression naming plugin directory names to
	  include.  Any plugin not matching this expression is excluded.
	  In any case you need at least include the nutch-extensionpoints plugin. By
	  default Nutch includes crawling just HTML and plain text via HTTP,
	  and basic indexing and search plugins. In order to use HTTPS please enable
	  protocol-httpclient, but be aware of possible intermittent problems with the
	  underlying commons-httpclient library.
	  </description>
	</property>
            可以將cookie資訊也放在這個檔案中,如新增
	<property>
		<name>cookie.value</name>
		<value>BAIDUID=24B253A73C44B95F9D0A876F23FCAAAA:FG=1;BDSVRTM=0</value>
	</property>
             接下來,修改原始碼src/plugin/protocol-httpclient/src/java/Http.java,

             在setConf()方法新增cookieValue變數讀取cookie值,在configureClient()方法給header新增Cookie

	public void setConf(Configuration conf) {
	        //其他程式碼略.....
		cookieValue = conf.get("cookie.value", "");
		//其他程式碼略....
       }

        private void configureClient() {
               //....
               headers.add(new Header("Cookie", cookieValue));
               //....
        }
      

            二.如果要抓取的頁面有分頁,但是頁碼的跳轉是用js方法

                  nutch會收集當前頁面的url,那麼如何將我們自己要想的url新增進去呢?

             首先解析要抓取頁面,一共有多少分頁.可以找到這個類src/plugin/parse-html/src/java/HtmlParser.java

             getParse(String url, WebPage page)方法中,

         utils.getText(sb, root);          // extract text
         text = sb.toString();             //這裡的text就是頁面的文字內容
             我們可以看到在DOMContentUtils.getTextHelper()方法遍歷了dom節點,通過使用DOM方法獲取到總頁數,然後可以組裝好

       url,在NUTCH_HOME/runtime/local/urls/目錄下生產存放url地址的檔案. 就是說,讓nutch在下一次抓取時候,去訪問你這次的url.

             另外,也可以在HtmlParser.java的sniffCharacterEncoding(ByteBuffer content) 方法,str變數是整個頁面的html程式碼,可以用              jsoup進行解析.

             如果不想將url儲存到檔案中,還有一個思路就是將url更新到crawldb中,看下HtmlParser類中如下的2行程式碼

       utils.getOutlinks(baseTag!=null?baseTag:base, l, root);
       outlinks = l.toArray(new Outlink[l.size()]);
             我們可以新增自己的url到outlinks集合中.

             三.不想深度抓取

                  預設情況下,nutch會儲存抓取頁面中的一些HTML標籤href屬性的url,下次執行命令時候就會抓取這些連結地址.有時候我們並不需要這些額外的資料.這種情況下HtmlParser類的outlinks變數就不需要處理了.

             儲存outlinks的程式碼在src/java/crawl/DbUpdateMapper的map方法

    Map<Utf8, Utf8> outlinks = page.getOutlinks();
    if (outlinks != null) {
      for (Entry<Utf8, Utf8> e : outlinks.entrySet()) {
                int depth=Integer.MAX_VALUE;
        Utf8 depthUtf8=page.getFromMarkers(DbUpdaterJob.DISTANCE);
        if (depthUtf8 != null) depth=Integer.parseInt(depthUtf8.toString());
        scoreData.add(new ScoreDatum(0.0f, e.getKey().toString(), 
            e.getValue().toString(), depth));
      }
    }
            

           四.eclipse執行原始碼問題

           執行Crawler的main方法時候會報錯. GeneratorReducer第100行, 程式碼如下:
           batchId = newUtf8(conf.get(GeneratorJob.BATCH_ID));
           這裡的conf.get(GeneratorJob.BATCH_ID)為空報錯.

           解決方法,修改GeneratorJob中的public Map<String,Object> run(Map<String,Object> args) 方法。新增以下程式碼

    // generate batchId 
       int randomSeed = Math.abs(new Random().nextInt()); 
       String batchId = (curTime / 1000) + "-" + randomSeed; 
       getConf().set(BATCH_ID, batchId); 
           同樣的,SolrIndexerJob的第40行,String batchId = (String)args.get(Nutch.ARG_BATCH);因為也為空值而報錯,這裡

           可以給batchId指定一個值.能達到執行原始碼正常就行,這時就可以DEBUG詳細的檢視nutch如何運行了.

           五.小結

           Nutch屬於Apache的, 支援分散式處理,包含web爬蟲和全文搜尋功能,看起來美美的.

           不過,用起來蠻複雜的,二次開發不夠靈活也略顯麻煩,抓取目標不特定,後期有變動的話,要修改的地方會很多.

           如果nutch能滿足你80%的需求,如果不考慮後期需求變動會有比較大的修改,看了原始碼後如果覺得自己可以hold住它,可以使用.

           否則個人建議還是自己開發會簡單些.