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檔案,新增
可以將cookie資訊也放在這個檔案中,如新增<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>
<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住它,可以使用.
否則個人建議還是自己開發會簡單些.