サンプル・プログラムの実行例
サンプル・プログラム
makeudic_mecab.php | サンプル・プログラム本体 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「PHPでGET/POSTでフォームから値を受け取る」「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
user_wiki.dic | サンプル・プログラムを使って作った辞書ファイル(シフトJIS) |
準備:各種定数
46: //表示幅(ピクセル)
47: define('WIDTH', 600);
48:
49: //Spinner - jQuery UI を使用するかどうか
50: define('USESPINNER', TRUE);
51:
52: //コスト(初期値)
53: define('COST_DEF', 10);
54: //コスト(最小値)→コスト計算する
55: define('COST_MIN', 0);
56: //コスト(最大値)
57: define('COST_MAX', 9999);
58:
59: //ユーザー辞書
60: define('FILE_UDIC_MECAB', 'user_wiki.dic');
61:
62: //Wikipedia見出しファイル
63: define('TITLES_WIKIPEDIA', 'https://download.wikimedia.org/jawiki/latest/jawiki-latest-all-titles-in-ns0.gz');
64:
65: //Wikipedia見出しファイル保存ファイル名
66: define('FILE_WIKIPEDIA', 'jawiki-latest-all-titles-in-ns0.gz');
67:
68: //ユーザー辞書CSV
69: define('FILE_WIKIPEDIA_CSV', 'user_wiki.csv');
70:
71: //MeCab実行プログラム:各自の環境に合わせて
72: define('MECAB', 'C:\Program Files\MeCab\bin\mecab.exe');
73:
74: //MeCab辞書作成プログラム:各自の環境に合わせて
75: define('MECABDICT', 'C:\Program Files\MeCab\bin\mecab-dict-index.exe');
76:
77: //システム辞書:各自の環境に合わせて
78: define('PATH_SYSDIC_MECAB', 'C:\Program Files\MeCab\dic\ipadic');
Wikipediaの見出し語は、"https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-all-titles-in-ns0.gz" からダウンロードできる。これを定数 TITLES_WIKIPEDIA に格納する。
解説:ユーザー辞書作成
241: /**
242: * ユーザー辞書を作成する
243: * @param int $cost コスト
244: * @param string $encode 文字コード
245: * @return string 処理結果
246: */
247: function make_userdic($cost, $encode) {
248: //平均コストテーブル
249: static $table = array(
250: 0,
251: 7697, 7087, 7572, 7441, 7566, 7352, 6810, 6209, 5871, 5963,
252: 5847, 5818, 5829, 5990, 5955, 5590, 5984, 5181, 5122, 5985,
253: 5122, 5122, 5122, 4437, 5122
254: );
255: //追加辞書(漢数字無変換用)
256: static $add_dic1 = array('幾', '何');
257: static $add_dic2 = array('十', '百', '千');
258: static $add_dic3 = array('', '万', '億', '兆', '京');
259:
260: $msg = 'ユーザー辞書ファイルを作成しました.';
261:
262: $buff = file_get_contents(TITLES_WIKIPEDIA);
263: if ($buff == FALSE) return 'エラー:Wikipediaタイトル・ファイルが見当たりません.';
264: $res = file_put_contents(FILE_WIKIPEDIA, $buff);
265: if ($res == FALSE) return 'エラー:Wikipediaタイトル・ファイルをダウンロードできません.';
266:
267: $infp = gzopen(FILE_WIKIPEDIA, 'r');
268: if ($infp == FALSE) return 'エラー:Wikipediaタイトル・ファイルを読み込めません.';
269: $outfp = fopen(FILE_WIKIPEDIA_CSV, 'w');
270: if ($infp == FALSE) return 'エラー:ユーザー辞書ファイルを作成できません.';
271:
272: while (! feof($infp)) {
273: $str = trim(gzgets($infp));
274: if (preg_match('/[^ぁ-んァ-ヶー一-龠]/ui', $str) == 1) continue;
275: /** skip
276: if (preg_match('/^[0-9|a-z|\W_]/ui', $str) == 1) continue;
277: if (preg_match('/_/ui', $str) == 1) continue;
278: if (preg_match('/曖昧さ回避/ui', $str) == 1) continue;
279: if (preg_match('/一覧/ui', $str) == 1) continue;
280: if (preg_match('/の登場人物/ui', $str) == 1) continue;
281: **/
282: if (mb_strlen($str) <= 1) continue;
283:
284: //コスト計算
285: if ($cost <= COST_MIN) {
286: $len = mb_strlen($str);
287: $cost = ($len > count($table) - 1) ? 5000 : $table[$len];
288: }
289: $outstr = $str . ',1288,1288,' . $cost . ',名詞,固有名詞,*,*,*,*,' . $str . ",*,*,wikipedia\n";
290: if ($encode != INTERNAL_ENCODING) {
291: $outstr = mb_convert_encoding($outstr, $encode, INTERNAL_ENCODING);
292: }
293: $res = fwrite($outfp, $outstr);
294: if ($res == FALSE) {
295: $msg = 'エラー:ユーザー辞書ファイルを作成できません.';
296: break;
297: }
298: }
299:
300: //追加辞書作成
301: $error = FALSE;
302: foreach ($add_dic1 as $ss1) {
303: if ($error) break;
304: foreach ($add_dic2 as $ss2) {
305: if ($error) break;
306: foreach ($add_dic3 as $ss3) {
307: $str = $ss1 . $ss2 . $ss3;
308: $cost = 10; //コスト固定
309: $outstr = $str . ',1288,1288,' . $cost . ',名詞,固有名詞,*,*,*,*,' . $str . ",*,*,wikipedia\n";
310: if ($encode != INTERNAL_ENCODING) {
311: $outstr = mb_convert_encoding($outstr, $encode, INTERNAL_ENCODING);
312: }
313: $res = fwrite($outfp, $outstr);
314: if ($res == FALSE) {
315: $msg = 'エラー:ユーザー辞書ファイルを作成できません.';
316: $error = TRUE;
317: break;
318: }
319: }
320: }
321: }
322:
323: fclose($outfp);
324: gzclose($infp);
325:
326: $cmd = '"' . MECABDICT . '" -d "' . PATH_SYSDIC_MECAB . '" -u "' . FILE_UDIC_MECAB .'" -f ' . $encode .' -t ' . $encode . ' ' . FILE_WIKIPEDIA_CSV;
327: exec($cmd);
328:
329: // unlink(FILE_WIKIPEDIA);
330: // unlink(FILE_WIKIPEDIA_CSV);
331:
332: return $msg;
333: }
gzgets を使って1行ずつ読み込み、ユーザー辞書作成のためのCSV形式に変換して FILE_WIKIPEDIA_CSV に出力する。
なお、TITLES_WIKIPEDIA には辞書として登録する必要のない見出しもあるので、これらは preg_match によって弾いている。
CSV形式のフォーマットは以下の通り。
表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音ここでは、左文脈IDと右文脈IDは固有名詞1288として固定にした。
コストは、その単語がどれだけ出現しやすいかを示している。小さいほど出現しやすいという意味になる。
ここでは、単語の文字列長に応じてコストを決定するテーブル $table を用意した。
このテーブルの値は、MeCabに標準で用意されているシステム辞書のコストの平均値を計算したものである。具体的には、'MeCab/dic/ipadic' に格納されているCSVファイルから、文字列長とコストをとりだし、文字列長毎のコストの平均を計算した。
このアイデアについては、「wikipediaのデータや顔文字辞書からmecabのユーザ辞書を作成するフレームワーク」を参考にした。
ただし、変数 $cost が指定されている場合は、その値に合わせて固定値とした。辞書ファイルを使うアプリケーション(例:PHPで日本語テキストを正規化)によっては、この辞書の固有名詞を優先させた方が良い結果を得られるので。
CSVファイル FILE_WIKIPEDIA_CSV が作成できたら、ここからMeCabの辞書作成ツール "mecab-dict-index"(定数 MECABDICT に定義)を使って辞書ファイルを作成する。
参考サイト
- MeCab:公式サイト
- PHPとKAKASIを使って単語に分解する:ぱふぅ家のホームページ
- PHPで日本語テキストを正規化:ぱふぅ家のホームページ
- C++ でテキストの正規化:ぱふぅ家のホームページ
- Windows 64bit で、mecab-python
- wikipediaのデータや顔文字辞書からmecabのユーザ辞書を作成するフレームワーク:livedoor Techブログ
ユーザー辞書は、Wikipediaの見出し語をすべて取り込むことにする。
(2022年7月2日)コストを指定できるようにした.pahooInputData対応, 文脈ID見直し
(2022年5月7日)PHP8対応,リファラ・チェック改良.コマンドラインからの実行対応(CUI版)