自然言語による検索ができるような工夫

タイトルだけ見るとスゴイ事をしているように見えてしまいますが(^^;ゞ、そんな仰々しい話では無いです。

名付けて.ね〜むのサイトで適当な文章を入力して検索すると、名詞と動詞のみを抽出して、検索対象にするようにしています。

こうする事で、登録される単語が、できるだけ"名詞or動詞一語"に限定されやすいようになる事を狙っています。

あまり自由度を高くして、「"○○を△△する関数"→"□□××"」みたいな対応関係を登録する仕組みにしてしまうと、検索する時に目的のものが得られにくくなってしまうかなと思い、今の形にしています。

どういう仕組みになっているの?

で、内部的にどうやって処理しているかと言うと、基本的には、MeCabを使って形態素に分解して、名詞と動詞のもののみを抜き出してくるようにしています。

ただ、単純に形態素分解するだけだと以下のような問題があって、ちょっとばかし工夫しています。

  • "○○する"という単語が"○○"と"する"に分割されてしまう。
  • "長さ"などの形容詞の名詞化された単語が、"長"と"さ"のように分割されてしまう。
  • "ファイルポインタ"のような複数の名詞からなる単語が、"ファイル"と"ポインタ"のように分割されてしまう。

上記3つのケースに関しては、特別ルールとして分割された形態素を繋げたものを、結果として出力するようにしています。

MeCabの結果取得で一苦労…

という訳で、日本語処理に関しては非常に優れもののMeCabたんなんですが、PHP側に形態素解析の結果を取り込むのに結構苦労してしまいました…。

というのも、開発をWindows上でやっているので、MeCab PHP extensionは使えず…。なので、mecabコマンドを直接叩いて、結果を文字列で取得してからゴニョゴニョする事にしました。

最初は、次のようなコードで実験…。

<?php
$mecab_exe = '"C:\Program Files\MeCab\bin\mecab.exe"';
$string = 'すもももももももものうち';
$result = shell_exec('echo '.$string.'|'.$mecab_exe);
echo $result;
?>

結果は…

すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
・Eぁ	名詞,一般,*,*,*,*,*
E	名詞,固有名詞,組織,*,*,*,*
・・	記号,一般,*,*,*,*,*
EOS

何だか、一部、文字化けしてしまう…。

色々試してみる内に、MeCabの問題ではなく、PHPでshell_execに日本語を引き渡した時点で文字化けしてしまっている事が分かりました。*1

困ったときのGoogle先生…という事で、以下のサイトなどを参考にさせてもらって、shell_execを使うのを諦めて、proc_openを使うようにしてみたら、うまく動くようになりました。
http://kudelab.com/archives/15

書き換えたコードは次のような感じ…。

<?php
$mecab_exe = '"C:\Program Files\MeCab\bin\mecab.exe"';
$string = 'すもももももももものうち';
$result = '';
$descriptorspec = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
);
$process = proc_open($mecab_exe, $descriptorspec, $pipes);
if (is_resource($process)) {
    fwrite($pipes[0], $string);
    fclose($pipes[0]);
    while (!feof($pipes[1])) {
        $result .= fread($pipes[1], 4096);
    }
    fclose($pipes[1]);
    proc_close($process);
}
echo $result;
?>

結果は…

すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
うち	名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS

おぉ、うまくいきました。


という訳で、今回はちょっとした苦労話なんぞを書いてみました。

こんな感じのサイト制作の裏話みたいのは、またちょこちょこ書いていこうと思います。

*1:SJISだと大丈夫なようなので、UTF-8を使っているのがよくなさそうな感じなんですが、今時のWebサービス制作は文字コードUTF-8にしたいですしねぇ…。