« 2008年06月 | メイン | 2008年09月 »
2008年07月11日
Mac OS X Leopard に「標準で」インストールされている MeCabを使ってみる
Mac OS X Leopard の Spotlight に MeCab が使われているらしいという情報を聞いたので、実際に深追いしてみました。いとも簡単に /usr/lib/libmecab* , /usr/include/mecab.h と /usr/lib/mecab/dic/apple/{ja,tc,sc} というディレクトリを発見しました。ts, sc は traditional/simplified Chinese (繁体字/簡体字) の略で、中国語の辞書だと推察されます。辞書のディレクトリはさらに dic/apple/ja/{LE,BE} という風に、エンディアンごとに分かれています。MeCabの辞書はエンディアン依存なので、こうするしかないのかもしれません。
さて、この辞書を使って、UTF8の文字列を流し込んでみたのですが、うまいこと解析してくれません。MeCabのバイナリ辞書形式には文字コードの情報が文字列で埋め込まれているので、その部分を バイナリエディタで見ると、UTF-16LE となっています。どうやら入出力を UTF-16LE にすれば形態素解析ができそうです。
確認のためのコード
#include <mecab.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iconv.h> char *iconv_convert_helper(iconv_t ic, const char *input, size_t ilen, size_t *length) { size_t olen = ilen * 4; char *result = (char *)malloc(olen); char *ibuf = (char *)input; char *obuf_org = result; char *obuf = result; size_t olen_org = olen; memset(result, 0, olen); if (ic == (iconv_t)(-1)) { exit(-1); } while (ilen != 0) { if (iconv(ic, (char **)(&ibuf), &ilen, &obuf, &olen) == (size_t)(-1)) { fprintf(stderr, "error in iconv\n"); free(result); return NULL; } } *length = olen_org - olen; obuf_org[*length] = '\0'; iconv_close(ic); return result; } char *utf8_to_utf16(const char *input, size_t ilen, size_t *olen) { iconv_t ic = iconv_open("UTF-16LE", "UTF-8"); return iconv_convert_helper(ic, input, ilen, olen); } char *utf16_to_utf8(const char *input, size_t ilen, size_t *olen) { iconv_t ic = iconv_open("UTF-8", "UTF-16LE"); return iconv_convert_helper(ic, input, ilen, olen); } int main (int argc, char **argv) { mecab_t *mecab; const mecab_node_t *node; char buf[8192]; char *buf2; mecab = mecab_new2("-d /usr/lib/mecab/dic/apple/ja/LE"); if (mecab == NULL) { fprintf(stderr, "error in mecab_new2: %s\n", mecab_strerror(NULL)); return -1; } while (fgets(buf, sizeof(buf), stdin)) { buf[strlen(buf) - 1] = '\0'; size_t olen = 0; buf2 = utf8_to_utf16(buf, strlen(buf), &olen); node = mecab_sparse_tonode2(mecab, buf2, olen); if (node == NULL) { fprintf(stderr, "error\n"); exit(-1); } node = node->next; for (; node->next != NULL; node = node->next) { char *r = utf16_to_utf8(node->surface, node->length, &olen); printf("%s|", r); free(r); } free(buf2); printf("\n"); } mecab_destroy(mecab); return 0; }
% gcc test.c -lmecab -liconv % echo 私の名前は中野です | ./a.out 私|の|名前|は|中野|です|
うひょー。分かち書きできます。品詞情報もあるみたいですが、Spotlight ではほとんど使われないようなので、一文字の品詞に省略されています。