ferretを試してみる + MeCabでTokenize


ferretというRubyのテキスト検索エンジンライブラリを見つけました。

404 Not Found

主要部分はCで書かれていて高速なようです。またチュートリアルを見る限りでは簡単に使えそうです。ただ、日本語用のTokenizerは用意されていないようなので、MeCabを利用して簡単なものを作成しながら試してみました。

インストール

% gem install ferret

そのほか、mecab、mecab-ipadic、mecab-rubyが適切にインストールされているとします。

文字コードはUTF-8を用いました。

使用

チュートリアルに従って一通り試してみたところで、MecabAnalyzer、MecabTokenizerを作りました。

ソースは以下の通りです。

#!/usr/bin/ruby -Ku

require ‘rubygems’ require ‘ferret’ require ‘MeCab’ include Ferret

class MecabAnalyzer def initialize(use_surface=false) @use_surface = use_surface end def token_stream(field, str) return MecabTokenizer.new(str, @use_surface) end end

class MecabTokenizer def initialize(str, use_surface=false) @mecab = MeCab::Tagger.new self.text = str @use_surface = use_surface end def text=(str) @text = str @n = @mecab.parseToNode(text) @n = @n.next # skip EOS @pos = 0 end attr_reader :text def next return nil if @n.stat == MeCab::MECAB_EOS_NODE features = @n.feature.split(/,/) t = @use_surface ? @n.surface : features[6] token = Analysis::Token.new(t, @pos, @pos+@n.rlength) @pos += @n.rlength @n = @n.next return token end end

以下、動作確認用のコード。

index = Index::Index.new(:analyzer => MecabAnalyzer.new)

index << {:id=>0, :content=>“寒くて我慢できない。”} index << {:id=>1, :content=>“今日は寒い一日になりそうです。\nそんな予感。”} index << {:id=>2, :content=>“今日もしないとね。“}

check tokenizer

mt = MecabTokenizer.new(index[0].load[:content]) while t = mt.next p t end

query = “寒く” puts “query: #{query}” index.search_each(query) do |id,score| p [id, score, index[id].load] puts index.highlight(query, id, :field => :content, :pre_tag => ”[”, :post_tag => ”]”, :excerpt_length => :all) end

実行結果は以下のようになりました。「寒い」と「寒く」が同一視されていることがわかります。

dara@wasabi:~/ferret$ ruby ferret_test.rb 
token["寒い":0:6:1]
token["て":6:9:1]
token["我慢":9:15:1]
token["できる":15:21:1]
token["ない":21:27:1]
token["。":27:30:1]
query: 寒く
[0, 0.0806559845805168, {:content=>"寒くて我慢できない。", :id=>"0"}]
[寒く]て我慢できない。
[1, 0.0537706576287746, {:content=>"今日は寒い一日になりそうです。\nそんな予感。", :id=>"1"}]
今日は[寒い]一日になりそうです。
そんな予感。

課題

次の段階としては、品詞に基づいて抽出する単語を任意に選択できるようにしたいところです。しかし、TokenizerとFilterが分離されているため、形態素解析の結果を利用してフィルタを行うためには、

などの工夫が必要になりそうです。とはいえ、ちょっとした応用ならばMecabTokenizer#nextにコチョコチョと書き加えれば済みそうですので、今回はここまでにしておきます。

Cで書いた方がよかろうという話もありますよね。