20 January 2014

網頁爬蟲相信很多人都寫過,尤其是在 web 2.0 那個時代,但這方面的技術我碰的很少,難得最近才有機會玩過一輪。不過我也不是著重在爬網址,而是花心力在處理網頁的內容上。這一番實作,發現了一些相當不錯的工具,跟大家分享。

jsoup

jsoup 是 html 網頁的 parser,這前面的文章提過一下,它的 DOM API 不是 Java 界常用的 org.xml/javax.xml 那一堆難用的 API,而是像 jQuery 看齊,使用 css selector 篩選元件。我整理了很多種類的網頁,還沒遇到它不能處理的,parser 容錯的能力很好。

另外字串的編碼的偵測也是很穩。在台灣,除了 UTF-8 之外,最常見的就是該死的 Big5 編碼。如果網站吐的 content-type 是對的,那處理還算簡單。但有些網站 meta 裡寫著 Big5,實際編碼卻是 UTF-8,遇到這種怪咖,Jsoup 還是能處理。真是個優值的好工具,收藏之。

fluent-hc

Jsoup 本身就可以吃 url,然後抓下來解析成 DOM,不過它的功能很簡陃。如果要應付各式各樣的網站,Apache HttpClient 仍是不二選擇。HttpClient 在 4.0 時做了大改版,跟 3.x 版時 API 完全不一樣,變得超難用。搞的大家不是繼續用 3.x,就是自己寫 wrapper,跟 java.util.Date 的慘狀一樣。

後來他們才又追加一個 fluent http client,故名思義,這個 client API 用起來如行雲流水,一行直覺的程式就能搞定。如果沒有特別需求,應該都盡量用 fluent-hc 來做 http request。推薦給各位 http client 4.0 的受害者。

rome

rome 是 RSS parser,超級古老的專案,在 Java 1.5 之前開發的。還好 RSS/Atom 的規格也是幾百年沒動了,堪用。我看到它的 package 是以 com.sun.* 開頭... 淚流滿面....

boilerpipe

解析網頁常見的需求就是去掉橫幅、邊條、廣告等等無關的資訊,直取網頁的本文。 boilerpipe 是個知名的工具,它不是靠 html 或是 css 的結構去猜本文的位置,而是根據文字與 tag 的密度比、title 與文章的相似性等等屬性去摘取本文。它使用新聞文章庫來訓練模型,取得一些假設的參數,例如連結的密度小於 0.33 時,該段落就有可能是本文。

當然這工具的模型是用英文的新聞來訓練。所以不是新聞文體的網頁失敗率就會變高,而中文的準確率又更低一點。我自己的經驗,最好的成功率約七成左右吧。

language-detection

language-detection 是判斷文章語言的工具,由日本人開發,可偵測 53 種語言,高達 99% 的辨識率。它的原理是從 wikipedia 的文章收集常用字段 (n-gram),然後造常用字段的表,以 json 格式儲存。每個語言字段表大小不一,我看繁體中文的表大約是 2000個字段。實際比對時,則是將測試的文章先切成字段,然後計算字段的出現機率。機率最高的自然就是對的語言了。

我自己實測結果,辨識率和它宣稱一樣好,繁體中文辨識率很高,而日文的更是沒錯過,太強了!

中文分詞器

我找到兩個,jcseg 以及 ik-analyzer,其中 jcseg 有支援繁體中文。lucene 裡也有個 lucene-analyzers-smartcn,則是由 ictclas 貢獻給 apache 開源使用。 這些工具我還沒開始用,但我猜遲早會遇到的,暫時先放在工具箱裡。它們都是大陸開發而且 Open Source。台灣呢?中研院是有語料庫的,不過鎖了起來,中文的研究還是大陸比較先進且開放。

Apache Tika

最後,還有一個工具是 Apache Tika ,專門做內文抽取的。除了網頁外,還支援 pdf/doc 等格式。我個人比較需要細部的控制和調整,所以這個套好的工具包我就沒試了。有興趣的人可以看看。


回響

可以用 Tag <I>、<B>,程式碼請用 <PRE>