サンプル・プログラムの実行例

サンプル・プログラム
makeudic_mecab.php | サンプル・プログラム本体 |
準備:各種定数
0045: //ユーザー辞書
0046: define('FILE_UDIC_MECAB', 'user_wiki.dic');
0047:
0048: //Wikipedia見出しファイル
0049: define('TITLES_WIKIPEDIA', 'https://download.wikimedia.org/jawiki/latest/jawiki-latest-all-titles-in-ns0.gz');
0050:
0051: //Wikipedia見出しファイル保存ファイル名
0052: define('FILE_WIKIPEDIA', 'jawiki-latest-all-titles-in-ns0.gz');
0053:
0054: //ユーザー辞書CSV
0055: define('FILE_WIKIPEDIA_CSV', 'user_wiki.csv');
0056:
0057: //MeCab実行プログラム:各自の環境に合わせて
0058: define('MECAB', 'C:\Program Files (x86)\MeCab\bin\mecab.exe');
0059:
0060: //MeCab辞書作成プログラム:各自の環境に合わせて
0061: define('MECABDICT', 'C:\Program Files (x86)\MeCab\bin\mecab-dict-index.exe');
0062:
0063: //システム辞書:各自の環境に合わせて
0064: define('PATH_SYSDIC_MECAB', 'C:\Program Files (x86)\MeCab\dic\ipadic');

Wikipediaの見出し語は、"https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-all-titles-in-ns0.gz" からダウンロードできる。これを定数 TITLES_WIKIPEDIA に格納する。
解説:ユーザー辞書作成
0355: /**
0356: * ユーザー辞書を作成する
0357: * @param string $encode 文字コード
0358: * @return string 処理結果
0359: */
0360: function make_userdic($encode) {
0361: //平均コストテーブル
0362: static $table = array(
0363: 0,
0364: 7697, 7087, 7572, 7441, 7566, 7352, 6810, 6209, 5871, 5963,
0365: 5847, 5818, 5829, 5990, 5955, 5590, 5984, 5181, 5122, 5985,
0366: 5122, 5122, 5122, 4437, 5122
0367: );
0368: //追加辞書(漢数字無変換用)
0369: static $add_dic1 = array('幾', '何');
0370: static $add_dic2 = array('十', '百', '千');
0371: static $add_dic3 = array('', '万', '億', '兆', '京');
0372:
0373: $msg = 'ユーザー辞書ファイルを作成しました.';
0374:
0375: $buff = file_get_contents(TITLES_WIKIPEDIA);
0376: if ($buff == FALSE) return 'エラー:Wikipediaタイトル・ファイルが見当たりません.';
0377: $res = file_put_contents(FILE_WIKIPEDIA, $buff);
0378: if ($res == FALSE) return 'エラー:Wikipediaタイトル・ファイルをダウンロードできません.';
0379:
0380: $infp = gzopen(FILE_WIKIPEDIA, 'r');
0381: if ($infp == FALSE) return 'エラー:Wikipediaタイトル・ファイルを読み込めません.';
0382: $outfp = fopen(FILE_WIKIPEDIA_CSV, 'w');
0383: if ($infp == FALSE) return 'エラー:ユーザー辞書ファイルを作成できません.';
0384:
0385: while (! feof($infp)) {
0386: $str = trim(gzgets($infp));
0387: if (preg_match('/[^ぁ-んァ-ヶー一-龠]/ui', $str) == 1) continue;
0388: /**
0389: if (preg_match('/^[0-9|a-z|\W_]/ui', $str) == 1) continue;
0390: if (preg_match('/_/ui', $str) == 1) continue;
0391: if (preg_match('/曖昧さ回避/ui', $str) == 1) continue;
0392: if (preg_match('/一覧/ui', $str) == 1) continue;
0393: if (preg_match('/の登場人物/ui', $str) == 1) continue;
0394: **/
0395: if (mb_strlen($str) <= 1) continue;
0396:
0397: //コスト計算
0398: $len = mb_strlen($str);
0399: $cost = ($len > count($table) - 1) ? 5000 : $table[$len];
0400: $outstr = $str . ',128,128,' . $cost . ',名詞,固有名詞,*,*,*,*,' . $str . ",*,*,wikipedia\n";
0401: if ($encode != INTERNAL_ENCODING) {
0402: $outstr = mb_convert_encoding($outstr, $encode, INTERNAL_ENCODING);
0403: }
0404: $res = fwrite($outfp, $outstr);
0405: if ($res == FALSE) {
0406: $msg = 'エラー:ユーザー辞書ファイルを作成できません.';
0407: break;
0408: }
0409: }
0410:
0411: //追加辞書作成
0412: $error = FALSE;
0413: foreach ($add_dic1 as $ss1) {
0414: if ($error) break;
0415: foreach ($add_dic2 as $ss2) {
0416: if ($error) break;
0417: foreach ($add_dic3 as $ss3) {
0418: $str = $ss1 . $ss2 . $ss3;
0419: $cost = 100; //コスト固定
0420: $outstr = $str . ',128,128,' . $cost . ',名詞,固有名詞,*,*,*,*,' . $str . ",*,*,wikipedia\n";
0421: if ($encode != INTERNAL_ENCODING) {
0422: $outstr = mb_convert_encoding($outstr, $encode, INTERNAL_ENCODING);
0423: }
0424: $res = fwrite($outfp, $outstr);
0425: if ($res == FALSE) {
0426: $msg = 'エラー:ユーザー辞書ファイルを作成できません.';
0427: $error = TRUE;
0428: break;
0429: }
0430: }
0431: }
0432: }
0433:
0434: fclose($outfp);
0435: gzclose($infp);
0436:
0437: $cmd = '"' . MECABDICT . '" -d "' . PATH_SYSDIC_MECAB . '" -u "' . FILE_UDIC_MECAB .'" -f ' . $encode .' -t ' . $encode . ' ' . FILE_WIKIPEDIA_CSV;
0438: exec($cmd);
0439:
0440: // unlink(FILE_WIKIPEDIA);
0441: // unlink(FILE_WIKIPEDIA_CSV);
0442:
0443: return $msg;
0444: }

gzgets を使って1行ずつ読み込み、ユーザー辞書作成のためのCSV形式に変換して FILE_WIKIPEDIA_CSV に出力する。
なお、TITLES_WIKIPEDIA には辞書として登録する必要のない見出しもあるので、これらは preg_match によって弾いている。

CSV形式のフォーマットは以下の通り。
表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音ここでは、左文脈IDと右文脈IDは128で固定にした。

コストは、その単語がどれだけ出現しやすいかを示している。小さいほど出現しやすいという意味になる。
ここでは、単語の文字列長に応じてコストを決定するテーブル $table を用意した。
このテーブルの値は、MeCabに標準で用意されているシステム辞書のコストの平均値を計算したものである。具体的には、'MeCab/dic/ipadic' に格納されているCSVファイルから、文字列長とコストをとりだし、文字列長毎のコストの平均を計算した。
このアイデアについては、「wikipediaのデータや顔文字辞書からmecabのユーザ辞書を作成するフレームワーク」を参考にした。

CSVファイル FILE_WIKIPEDIA_CSV が作成できたら、ここからMeCabの辞書作成ツール "mecab-dict-index"(定数 MECABDICT に定義)を使って辞書ファイルを作成する。
参考サイト
- MeCab:公式サイト
- PHPとKAKASIを使って単語に分解する:ぱふぅ家のホームページ
- C++ でテキストの正規化:ぱふぅ家のホームページ
- Windows 64bit で、mecab-python
- ルー語変換を MeCab だけで実現:きまぐれ日記
- wikipediaのデータや顔文字辞書からmecabのユーザ辞書を作成するフレームワーク:livedoor Techブログ
ユーザー辞書は、Wikipediaの見出し語をすべて取り込むことにする。
(2022年5月7日)PHP8対応,リファラ・チェック改良.コマンドラインからの実行対応(CUI版)