Sphinxのインデックス作成時にMeCabのユーザー辞書を利用する

MeCabのユーザー辞書を利用してSphinxのインデックスを作成する方法を紹介します。
2018.09.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。サービスグループの武田です。

先日Sphinxの分かち書きアルゴリズムにMeCabを使用する方法をエントリしました。

Sphinxの分かち書きアルゴリズムにMeCabを使用する

その最後に クラスメソッド などの固有名詞がインデックスされなくなってしまったという課題が残っていました。今回はMeCabのユーザー辞書を利用することで改善できそうということで、その方法を紹介します。

環境

今回は次の環境で検証しました。なおSphinxの言語は日本語を指定しています(language = 'ja')。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G65

$ python3 -V
Python 3.7.0

$ pip3 -V
pip 18.0 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)

$ pip3 list | grep -e Sphinx -e mecab -e jsbeautifier
jsbeautifier             1.8.6
mecab-python3            0.7
Sphinx                   1.7.4

MeCabをそのまま使ったケース

まずは前回のエントリと同様にMeCabをそのまま使った場合に、どのようにインデックスが作られるのかを確認します。conf.pyは同じ内容です。

conf.py

html_search_options = {
    'type': 'sphinx.search.ja.MecabSplitter',
    'dic_enc': 'utf-8',
    'dict': '/usr/local/lib/mecab/dic/mecab-ipadic-neologd'
}

次にSphinxをビルドし、作成されたインデックスの内容を確認します。ビルド対象のドキュメントは実際に運用しているもので、そこから一部抜粋してみます。

$ make clean && make html
$ cat build/html/searchindex.js \
  | python3 -c 'from sys import stdin; print(stdin.readline().encode().decode("unicode-escape"))' \
  | js-beautify \
  | grep -e クラス -e メソッド -e メンバーズ \
  | grep -v titles

  "クラス": [2, 4],
  "クラスメソッドメンバーズ": [0, 4],
  "クラスメソッドメンバーズポータル": 4,
  "メソッド": [2, 4],
  "メンバーズ": [0, 1, 3],
  "メンバーズポータル": 3,
  "クラスメソッドメンバーズ": 1,
  "メンバーズ": [2, 4],
  "メンバーズポータル": 2,

確かに クラスメソッド がインデックスされていないですね(クラスとメソッドに分かれてしまっている)。

MeCabのユーザー辞書を利用するケース

まず大前提の整理です。MeCabには、システム辞書ユーザー辞書 の2種類の辞書があります。そのため自分で辞書に単語を追加したい場合、どちらかの辞書を使用することになります。今回の構成ではmecab-ipadic-NEologdをシステム辞書として利用しているためそこに手を加えるか、ユーザー辞書を用意することになります。

ところで、Sphinxのhtml_search_optionsにはシステム辞書を指定するオプションはありますが、ユーザー辞書を指定するオプションがありません。そうするとシステム辞書を使うしかないかなとも思ったのですが、結局はMeCabの話なのでそっちで解決できないかと調べました。

調べた結果、MeCabのコマンドラインオプションか、設定ファイルでユーザー辞書を指定できることがわかりました。起動オプションはSphinx経由では指定できませんでしたが、設定ファイルならなんとかなりそうです。次に設定ファイルの指定方法、優先順位を調べました。簡潔にまとめると次のようになります(UNIX環境の場合)。

  1. コマンドラインオプションの-rまたは--rcfileで指定されたファイル
  2. ~/.mecabrcファイル(環境変数HOMEが設定されている場合)
  3. 環境変数MECABRCで指定されたファイル
  4. /usr/local/etc/mecabrcファイル
    • echo "$(mecab-config --sysconfdir)/mecabrc"で確認できます

このうち1は採用できません(コマンドラインオプションが指定できないため)。2、3、4はどれでも採用できそうですが、ユーザー辞書および設定ファイルを一緒にリポジトリで管理できると便利そうですので、3を採用してみます。

方針が決まったのでユーザー辞書を用意していきます。まずはCSVファイルです。

/path/to/classmethod.userdic.csv

クラスメソッド,-1,-1,1,名詞,固有名詞,組織,*,*,*,クラスメソッド,クラスメソッド,クラスメソッド

次にこのCSVファイルをコンパイルします。

$ cd /path/to
$ /usr/local/Cellar/mecab/0.996/libexec/mecab/mecab-dict-index \
  -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd \
  -u classmethod.dic \
  -f utf-8 \
  -t utf-8 \
  classmethod.userdic.csv

reading classmethod.userdic.csv ... 1
emitting double-array: 100% |###########################################|

done!

コンパイルできましたね。続いてmecabrcファイルを用意します。

/path/to/mecabrc

dicdir = /usr/local/lib/mecab/dic/mecab-ipadic-neologd
userdic = /path/to/classmethod.dic

最後に、conf.pyでシステム辞書を指定する必要がなくなったのでその設定は削除してしまいます。

conf.py

html_search_options = {
    'type': 'sphinx.search.ja.MecabSplitter'
}

これで準備ができました。それでは作成したユーザー辞書を利用してインデックスを作成してみます。

$ export MECABRC=/path/to/mecabrc
$ make clean && make html
$ cat build/html/searchindex.js \
  | python3 -c 'from sys import stdin; print(stdin.readline().encode().decode("unicode-escape"))' \
  | js-beautify \
  | grep -e クラス -e メソッド -e メンバーズ \
  | grep -v titles

  "クラスメソッド": [0, 2, 4],
  "メンバーズ": [0, 3],
  "メンバーズポータル": [3, 4],
  "クラスメソッド": 1,
  "メンバーズ": [1, 2, 4],
  "メンバーズポータル": 2,

クラスメソッド がきちんとインデックスされています!

まとめ

SphinxからMeCabを利用する際の、ユーザー辞書の使い方を調べてみました。途中まではシステム辞書でどうにかしないといけないかなと半ば諦めかけていましたが、ユーザー辞書が簡単に使えそうでよかったです。