2009年10月11日

Sphinxの検索を日本語対応にする

宇都宮のスフィンクス

写真は内容とは関係なく、栃木県宇都宮市のスフィンクスです。闇夜にいきなり現れるとかなりコワイです。

Sphinxの検索機能の日本語対応をしてみました。リンク先にはパッチ済みのSphinxが置いてあります。Sphinxは検索関連に関しては、かなり英語にハードコードされていましたので。やったことは以下の通り。

  • 日本語対応のSplitterの作成
  • 設定オプションに検索言語切り替えを追加
  • stemmingアルゴリズム、 stop wordsも検索言語と連動して切り替わるように変更
  • Sphinx-devのメーリングリストに、機能拡張要望をメール

日本語対応のSplitterの作成

まずやってみたのはSplitterの作成。Sphinxでは欧米言語を想定しているので、re.compile(r'\w+(?u)')という正規表現で単語を区切っています。何をやっているかというと、空白文字での区切りなので、日本語文字だと分けられません。日本語や中国語や韓国語は単語の意味などを類推したりしながら、単語を区切る処理が必要になります。形態要素分析というカテゴリの自然言語アルゴリズムです。

Sphinxは、ソースのreStructuredTextからHTMLにビルドするときに、ドキュメントを解析して、インデックスを作成して、JavaScriptのソースファイルとして出力します。実行時にはJavaScriptを使って検索をかけます。全部ブラウザ上で実行しちゃうのでサーバは不要というカラクリです。そんなこともあるのでインデックスが巨大になるN-Gram方式は使えません。

単なるインデックス作成のためには品詞とかまでは知る必要がないので、分かち書きというレベルの処理で大丈夫です。今回利用してみたSplitterは以下の3種類。

  • TinySegmenterPython実装。自分でも移植したんだけどコードを置いてきてしまったのでnyama++さんの実装を利用させてもらいました。
  • Mecab。C言語で実装された形態要素解析エンジン。ローカルで動かすならOSSではたぶん今のところ最強。
  • Yahoo!のWeb API。性能はいいらしい。

どれも一長一短あって、TinySegmenterはpure pythonなのでSphinxにバンドルするには最適。ただし性能はやや落ちます。Mecabは性能は高いけどC言語のモジュール。10MBぐらいあるので、バンドルするには難ありだし、Windowsとかのことを考えるとコンパイル前提で配るのも困難。Yahoo!APIはネットワーク接続が必要なのと、アプリケーションIDをユーザごとに登録する必要があるので気軽に使うには難あり。あと、後から分かったけど、結構重いです。ということで、3つとも実装してオプションで切り替えるようにしました。デフォルトはTinySegmenterなので、何もしなくてもひとまず動き、いい結果が欲しければちょっと努力してください、という感じになりました。

検索言語切り替えオプションの追加

ということで、言語切り替えオプションも追加します。それぞれの言葉を話す人が追加しやすいように、フォルダを作って、言語ごとにモジュール化する作戦。そんでもって、そのモジュール名を指定します。本格的なプラグイン方式にしてもよかったけど、シンプルな実装にしてみました(search_languages/__init__.py参照)。config.pyにオプションを追加して、search.pyの中で、単語区切りの処理などで、指定された言語のクラスを利用するようにしました。

もともと拡張機能の開発ができるようにAPIがそろっているので、オプションを追加するのも簡単ですね。

Stemming処理とStop words

複数形などで、変化した単語の末尾を元に戻す処理をStemming処理と呼ぶらしいです。今回初めて知りました。後は、「この単語は一般的な単語だから検索対象から外しますよ」というStop words。Sphinxではこれも英語にハードコードされていました。これも、各言語ごとのモジュールに追い出して、切り替えられるようにしました。ちなみに、Stemming処理はPython実装とJavaScript実装の両方を持っています。Stop WordsもPythonとJavaScriptの両方で持っていました。

Python側はモジュールのコンテンツを利用するようにして、JavaScriptは文字列で持っていてテンプレートの仕組みを使って展開するようにしました。思った以上に変更箇所が広がってしまいましたが、ブレークポイント(というか例外)を仕掛けたりしながら動かしてみて、テンプレート展開場所を突き止めて、そいつのコンテキスト(テンプレート展開時に渡せる変数)に入れて、という感じで。

これができたおかげで、英語以外の多くの言語の人にもメリットとして訴求できるポイントができました。

Sphinx-devのメーリングリストに、機能拡張要望をメール

で、最後に開発元にメールしました。パッチを作り続けるのは大変だし、やはり本流に入って欲しいところ。SphinxのMLは動きが悪い(たぶん開発者の人が忙しい)ので、結果が出るのは時間がかかるかもしれないけどね。さて、どういう反応が帰ってくるか楽しみです。

日本語検索対応のSphinxを使うには?

ここに置いてあるSphinxのコードを落としてきてインストールしてください。現時点の最新版のSphinxに対して変更をしていますので、基本的にはふつーのSphinxです。

日本語設定をするには、conf.pyにhtml_search_languagehtml_search_language_optionを追加します。追加しないと、デフォルトでは英語の動作になります。html_search_language'ja'を設定します。html_search_language_optionは辞書型です。デフォルトではTinySegmenterを使うようになっていますが、エンジンを切り替えるには"type"というキーに種類を入れます。

  • default: TinySegmenterを使います。
  • mecab: Mecabを使います。
  • yahoo: Yahoo!APIを利用します。

mecabを設定した場合には、libpathというパラメータを設定して、mecabのダイナミックリンクライブラリへのパスを設定します。ctypesから利用されます。yahooを設定した場合には、appidというオプション(必須)を設定してして、Yahoo!のウエブサイトから取得したアプリケーションIDを文字列で入れます。アプリケーションIDは流用したり、公開したりしちゃいけませんよ、ということになっていますので、Sphinxのソースを公開リポジトリに入れている方はご注意を。別ファイルにして、open関数で実行時に読み込む(ファイル自体は登録していない別ファイルに)というのがいいと思います。

posted by @shibukawa at 09:44 | Comment(810) | TrackBack(1) | Python はてなブックマーク - Sphinxの検索を日本語対応にする
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/32831225
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック

Sphinx日本語検索対応の1.0版
Excerpt: by GoodImages under CC BY-NC-ND 写真は、イギリスのSphinx Statueというやつだそうで。本当の名前かは知らないけど。 以前に行った、Sphinxの検索の多..
Weblog: 渋日記
Tracked: 2010-09-29 10:03
検索ボックス

Twitter

www.flickr.com
This is a Flickr badge showing public photos and videos from shibukawa.yoshiki. Make your own badge here.
<< 2016年09月 >>
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  
最近の記事
カテゴリ
過去ログ
Powered by さくらのブログ