PHPで漢数字混じりのテキストを半角数字に統一する

(1/1)
ネットの新聞記事を利用する際、漢数字が混じっている場合があり、これを横書きのテキストにすると読みにくい。そこで PHP を使い、漢数字混じりの日本語テキストを半角数字に統一するプログラムをつくってみることにする。
「八戸市」「千灯明」といった名詞に含まれる漢数字を半角数字に変換しないようにするため、「PHP で形態素解析を行う」で紹介した「日本語形態素解析 Web サービス」を利用する。

サンプル・プログラム

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

漢数字混じりのテキストを半角数字に統一検索

サンプル・プログラムの解説:準備

0021: //Yahoo! JAPAN Webサービス アプリケーションID
0022: //http://help.yahoo.co.jp/help/jp/developer/developer-06.html にて登録のこと.
0023: define('APPLICATION_ID', '**************************************');
0024: 
0025: //リクエストURL
0026: define('REQ_URL_YAHOOPARSE', 'http://jlp.yahooapis.jp/MAService/V1/parse');
0027: 
0028: //MeCabの実行プログラム
0029: define('MECAB', 'C:\Program Files (x86)\MeCab\bin\mecab.exe');

日本語形態素解析 Web サービス」を利用するためには、アプリケーション ID を取得する必要がある。http://help.yahoo.co.jp/help/jp/developer/developer-06.html から無料で取得できる。
取得した ID は定数 REQ_URL_YAHOOPARSE に格納すること。

このプログラムでは、例文として、下記のテキストを用意した。

太宰府天満宮で九月二十五日夜、菅原道真公をしのび、慰霊する「千灯明」があった。今月 20 日に始まった神幸式大祭の最後を飾り、9百年以上前から続く伝統の神事だ。
午後8時、境内の心字池の周囲に千本のろうそくがともされると、池にかかる太鼓橋などが浮かび上がった。

サンプル・プログラムの流れ

PHPで漢数字混じりのテキストを半角数字に統一する

サンプル・プログラムの解説:変換処理

0451: /**
0452:  * 漢数字混じりのテキストを半角数字混じりテキストに変換する
0453:  * @param string $str 漢数字混じりテキスト
0454:  * @param string $func 形態素解析に使う関数
0455:  * @return strin 変換後テキスト
0456: */
0457: function convert_kan2num($str$func) {
0458:     //数字パターン
0459:     $pat_kannum = '/^[01234567890123456789〇一二三四五六七八九十百千万億兆京]+$/ui';
0460: 
0461:     //中黒の小数点
0462:     $str = preg_replace_callback('/([0123456789〇一二三四五六七八九十百千万億兆京]+)・([01234567890123456789〇一二三四五六七八九十百千万億兆京]+)/iu',
0463:         function ($mat) {
0464:             return kan2num($mat[1], 3) . '.' . kan2num($mat[2], 3);
0465:         }, $str);
0466: 
0467:     //形態素に分解:Yahoo!JAPAN 日本語形態素解析Webサービス
0468:     $items = array();
0469:     $func($str$items);
0470: 
0471:     //結果を1単語ずつ取得
0472:     $dest = '';
0473:     $flag = FALSE;
0474:     $numstr = '';
0475:     $i = 0;
0476:     for ($i = 0; $i < count($items); $i++) {
0477:         if ($flag == FALSE) {
0478:             if (preg_match($pat_kannum$items[$i]['surface']) > 0) {
0479:                 $numstr = $items[$i]['surface'];
0480:                 $flag = TRUE;
0481:             } else {
0482:                 $dest .= $items[$i]['surface'];
0483:             }
0484:         } else {
0485:             if (preg_match($pat_kannum$items[$i]['surface']) > 0) {
0486:                 $numstr .= $items[$i]['surface'];
0487:                 $flag = TRUE;
0488:             } else if ($items[$i]['pos'] == '名詞') {
0489:                 $dest .= $numstr . $items[$i]['surface'];
0490:                 $numstr = '';
0491:                 $flag = FALSE;
0492:             } else {
0493:                 $dest .= kan2num($numstr, 2) . $items[$i]['surface'];
0494:                 $numstr = '';
0495:                 $flag = FALSE;
0496:             }
0497:         }
0498:     }
0499:     if ($flag == TRUE) {
0500:         $dest .= kan2num($numstr, 2);
0501:     }
0502: 
0503:     return $dest;
0504: }

入力テキストを改行で 1行ずつに切り出し、ユーザー関数 convert_kan2num に渡し、漢数字混じりのテキストを半角数字に統一していく。

まず、テキストを日本語形態素解析 Web サービスに渡し、形態素に分解する。後述するように、形態素の品詞を取得することが重要であるためだ。この WebAPI については「PHP で形態素解析を行う」で紹介しているので、そちらを参考にしてほしい。

分解された形態素を結合して変数 $dest に代入していく過程で、漢数字を半角数字に変換する。
まず、その形態素が漢数字なら、漢数字をバッファリングする変数 $numstr に代入し、$flag を TRUE にする。$flag は前の形態素が漢数字かどうかを保持することになる。
その形態素が漢数字でなければ、半角数字変換後のテキストを格納する変数 $dest に追加する。

前の形態素が漢数字でなく、その形態素が漢数字なら、変数 $numstr に代入し、$flag を TRUE にする。
前の形態素が漢数字でなく、その形態素が漢数字でなければ、そこで漢数字が終了したものとみなし、ユーザー関数 kan2num を使って半角数字に変換する。ユーザー関数 kan2num は、「PHP で半角数字を漢数字にする」で作ったユーザー関数だ。

ここで注意が必要なのが、漢数字に続く形態素の品詞である。
例文で「千本」の部分は、「千(名詞)」と「本(接尾語)」に分解される。これはそのまま kan2num を使って半角数字「1000 本」に変換すればいい。
一方、「千灯明」の部分は、「千(名詞)」と「灯明(名詞)」に分解される。これをそのまま半角数字に変換すると、「1000 灯明」となってしまう。
そこで、漢数字の後に名詞が続く場合は、2 つの形態素を合わせて 1 つの名詞とみなし、変換を行わないようにした。

参考サイト

(この項おわり)
header