こんにちは。Sleipnir Mobile for Android 開発担当の西田です。
最近 Android アプリで、日本語テキストから頻出キーワードを抽出したいなあ等といったことを考えており、ちょっと調べてみました。
まずは 日本語の形態素解析ライブラリの Mecab を使おうと思いつくわけですが、これをアプリに組み込むにはちょっと辞書のサイズが大きすぎる感じです。(50MB 以上!)なのでどっかのサーバーで API を用意してやるのが良さげな感じです。
Mecab には各種スクリプト言語のバインディングが用意されているので、今回は Ruby でやることにしました。
まずは Mecab + Ruby バインディング + 辞書をインストールします。Ubuntu 10.04 だと以下のようなコマンドでインストールできます:
sudo aptitude install ruby1.9.1 libmecab-ruby1.9.1 mecab-ipadic-utf8
そして、標準入力のテキストに含まれるキーワードを出現回数降順に出力するプログラムです。
#!/usr/bin/env ruby1.9.1 # -*- encoding: utf-8 -*- require 'MeCab' # キーワード=>出現回数 $word_count_map = Hash.new $word_count_map.default = 0 def proc_line mecab, line compound_noun = nil node = mecab.parseToNode(line) while node category = node.feature.force_encoding("utf-8").split(',')[0] noun = (category == '名詞' ? node.surface.force_encoding("utf-8") : nil) node = node.next if noun !~ /[^!-@\[-`{-~ 「」]/ # 数字/記号以外を含む名詞のみカウントする count_word compound_noun if compound_noun compound_noun = nil elsif !compound_noun compound_noun = noun elsif compound_noun =~ /\W$/ && noun =~ /^\W/ compound_noun << noun # 日本語の連続する名詞は繋げる else count_word compound_noun compound_noun = noun end end count_word compound_noun if compound_noun end def count_word word return if word.lengthb[1]) }.each do |word, count| puts format("%2d: %s", count, word) end
このプログラムのポイントは 3 つです。
- ● Mecab から得られる文字列は ASCII-8BIT と認識されているので force_encoding(“utf-8”) で UTF-8 に認識させます。
- ●日本語の複合名詞がぶつ切りにされてしまうので、非ASCII文字を含む名詞が連続する場合は連結します。
- ●記号単体も名詞として認識されてしまうので、明示的に省きます。
それでは実際に試してみた結果です。https://market.android.com/details?id=jp.co.fenrir.android.sleipnir の概要からキーワードを抽出してみました。長いので上位 50 件のみ掲載しています。
15: ページ 14: タブ 7: 表示 7: Sleipnir 7: こと 5: 操作 5: 検索 5: Android 5: メニュー 5: Mobile 4: フリック 4: ブックマーク 4: その他 3: 同期 3: ジェスチャ 3: 履歴 3: 機能 3: for 3: 設定 3: 長押 3: 可能 2: ブックマーク同期 2: 新規タブ 2: ファイル 2: 復元 2: ダウンロード 2: Fenrir 2: Pass 2: リンク 2: 利用 2: ページ内 2: Go 2: And 2: Hold 2: 画像 2: ズームイン・ズームアウト 2: 自動的 2: ブックマークインポート 2: 意見 2: 片手 2: 要望 2: 時計回り 2: 使い方 2: Facebook 2: タブグループ 2: たくさん 1: プライバシー設定 1: ウェブページ 1: サムネイル 1: 配置
期待通りの結果が得られました。あとは利用シーンに合わせて重み付けしてやれば、使い物になりそうな感じです。