2012年09月11日

boilerpipeを使ってみる

■概要

HTMLから本文を抽出してSolrに登録する用事があったので、Javaの本文抽出ライブラリを探してみたところ、boilerpipeという子を見つけた。

英語色が強そうだけど、そこそこに精度は出そうに見えたので使ってみた。


■導入

とりあえずjarをダウンロード
http://code.google.com/p/boilerpipe/downloads/list

もしくはMavenから
http://mvnrepository.com/artifact/de.l3s.boilerpipe/boilerpipe


■本文抽出を実行してみる

URL url = new URL("http://www.yahoo.co.jp/");
String text = DefaultExtractor.getInstance().getText(url);
System.out.println(text);

これだけで実行できる。

試しにうちのブログのこのページを解析してみる。

「コンテンツ」タブを選択し、「言語設定」を開く。
「日本語 [ja]」が一番上にいると思うので、下へ持って行きOK。
「全般」タブの「言語」ボタンをクリック。
「日本語(日本) [ja-JP]」だけになっていると思うので、「追加」をクリックし、「英語 [en]」とか「英語(米国)[en-US]」あたりを追加する。
最後に「日本語」を一番下に持ってきてOK。
ブラウザを英語サイトから落としてインストールすれば、メニューとかも英語になっていてより良い気がした。
それならいっそOSごと英語にしてしまおうかと思ったけど、そうすると日本語使う時に問題が出た。
ところでChormeは既にバージョン20までいってるんだ。100になったらお祝いとかするんかな。

ところどころ本文中の要素が飛ばされてしまっている。


■Extractorを変えてみる

上記ではDefaultExtractorを使ったけど、JavaDocを見てみると、他にも何種類かExtractorが用意されている。

例えばArticleExtractorはニュース記事向けらしく、たしかにYahooニュースの記事に対して実行したらうまく結果が取れた。説明文にはニュース用にヒューリスティックな数値を加えたものと書かれていた。

KeepEverythingWithMinKWordsExtractorは指定文字数以上の要素の中身を全部抽出する。ただ、単語の解釈が英語向けのようで日本語の場合はうまく動かなかった。

ソースを見てみると、de.l3s.boilerpipe.util.UnicodeTokenizerというクラスがいて、そこで空白や分割に関与しそうな記号でsplitする処理が書かれていた。


■UnicodeTokenizerを書き換えてみる

boilerpipeはカスタマイズされることを想定した作りになっている。けど、UnicodeTokenizerの部分は簡単には切り替えられないように見える。

そこでKuromojiを使いTokenizerを形態素解析を利用する形に書き換えてみる。

public static String[] tokenize(final CharSequence text) {
  Tokenizer tokenizer = Tokenizer.builder().mode(Mode.SEARCH).build();
  List<Token> tokens = tokenizer.tokenize(text.toString());
  String[] array = new String[tokens.size()];
  int idx = 0;
  for (Token token : tokens)
    array[idx++] = token.getSurfaceForm();
  return array;
}

変更してみたところ、取得される範囲がさっきより広くなった。うちのブログだとCopyrightのところまで本文に入るなど、ちょっと広がり過ぎてしまった。

微妙なバランスで成り立っているものなので、こういう小手先のことをするのはやはり良くない。

まぁ、用途的に広く取れてしまう分には構わないから良いか。それとも言語が違う日本のライブラリを使うか。