Kouhei Sutou
kou****@clear*****
2013年 9月 20日 (金) 16:12:19 JST
須藤です。 In <CANM+Hhcu=Y--BsHq3nfiJPaJ1N2Rhu0XFTeb54ms=HA0dn****@mail*****> "[groonga-dev,01791] mecabトークナイザでのtoo long sentenceの回避方法について" on Fri, 20 Sep 2013 08:43:32 +0900, Naoya Murakami <visio****@gmail*****> wrote: > mecabのtoo long sentenceについて、なにかいい回避方法案はないでしょうか? 今回の入力は改行を越えて意味が繋がっていないんですよね。例え ば、 私の 名前は 中野です。 とあったときに本当は「私の名前は中野です。」という意味だけど 横に長くなるので開業している、ということはないですよね、とい うことです。(私が書くメールの本文は30文字くらいずつで改行し ていますが、そのような改行の使い方ではないですよね、というこ とです。) であれば、mecab_sparse_tostr2()に渡す直前で改行で区切って、n 回mecab_sparse_tostr2()を呼ぶのがよいのではないかと思いました。 s = mecab_sparse_tostr2(tokenizer->mecab, normalized_string, normalized_string_length); ... というのを char **normalized_lines = split_to_lines(normalized_string, normalized_string_length); for (; *normalized_lines; normalized_lines++) { s = mecab_sparse_tostr2(tokenizer->mecab, *normalized_lines, strlen(*normalized_lines)); ... } みたいな感じにするイメージです。(実際はchar **を作らないで mecab_sparse_tostr2()に渡す文字列の長さを調整してメモリを割り 当てないようにすると思います。) n回mecab_sparse_tostr2()すると、↑でいうsをぜんぶ結合しない といけないのが面倒なところです。もともとは GRN_PLUGIN_MALLOC()していたのですが、そうすると結合するとき にメモリを拡張してとかしないといけなくて面倒なので GRN_TEXT_PUTS()でそこらへんを気にせずに追加できるようにして おきました。 https://github.com/groonga/groonga/blob/master/plugins/tokenizers/mecab.c#L157 ただ、問題があって。。。 NormalizerAutoは改行を削除するので正規化後は改行があった位置 がわからなくなるのです。しかーし、今回のケースでは必ず「<BR>」 が入っているようなので、正規化後の文字列を「<BR>」で区切って mecab_sparse_tostr2()をn回呼ぶようにするのがいいんじゃないか と思います。 > なお、コマンドラインからMecabに直接渡せば、too long sentenseは > 発生しませんでした。 mecabコマンドのソースをながめてみたところ、mecabコマンドでは 改行毎にmecab_sparse_tostr2()相当の処理をしていました。その ため、「too long sentence.」なエラーにはならないのだと思いま す。また、1行が長すぎるときは input-buffer overflow. The line is split. use -b #SIZE option. というエラーがでます。(最後の2行ででている) % mecab -Owakati < mecab_too_long_sentense_CRchar.sql > /dev/null CREATE DATABASE IF NOT EXISTS mecab _ too _ long _ sentense ; use mecab _ too _ long _ sentense ; drop table ftext ; CREATE TABLE IF NOT EXISTS ` ftext ` ( ` id ` int ( 10 ) NOT NULL , ` description ` longtext NOT NULL , PRIMARY KEY (` id `), FULLTEXT KEY ` description ` (` description `) COMMENT ' parser " TokenMecab ", normalizer " NormalizerAuto "' ) ENGINE = mroonga DEFAULT CHARSET = utf 8 ; INSERT INTO ` ftext ` (` id `, ` description `) VALUES input-buffer overflow. The line is split. use -b #SIZE option. input-buffer overflow. The line is split. use -b #SIZE option. このチェックはmecab_sparse_tostr2()相当の処理に渡す前に実行 しているので、やはり「too long sentence.」なエラーにはならな いのだと思います。 > <環境> > CentOS6.4 > groonga 最新マスタ > Mecab 0.994 (groongaのyumリポジトリのもの) > unidic > > <再現可能なデータ> > https://github.com/naoa/groonga-saigen ありがとうございます! データがあってとても助かりました! CentOS 6でWINGリポジトリをつかったやつだと再現したのですが、 Debian GNU/Linuxのパッケージでは再現しなかったのがなぞです が。。。 -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270) groongaサポート: http://groonga.org/ja/support/ パッチ採用はじめました: http://www.clear-code.com/recruitment/ コミットへのコメントサービスはじめました: http://www.clear-code.com/services/commit-comment.html