カロリー計算〜その2〜
の続き。
今度は、これをシステムの方で検索しやすいようにしなければならない。
日本語は超面倒で漢字や日本語があるため、ややこしい。
例えば、みかん一つにしても、
みかん
蜜柑
ミカン
オレンジ(←ちょっと強引か)
の全てにヒットする必要がある。
これは難しすぎる。
そこで、とりあえず携帯電話のアカサタナ検索みたいに、全てをひらがな検索すればいいんじゃね?目次みたいに。
ってことで、エクセルを起動し、名称の右に列を追加し、一つ一つ手入力・・・、できるわけがない。
そこで、mecab を使おうと思った。
mecab 京都大学情報学研究科−日本電信電話株式会社コミュニケーション科学基礎研究所 共同研究ユニットプロジェクトを通じて開発されたオープンソースな形態素解析エンジン。 言語, 辞書,コーパスに依存しない汎用的な設計を 基本方針としています。 パラメータの 推定に Conditional Random Fields (CRF) を用 いており, ChaSenが採用している 隠れマルコフモデルに比べ性能が向上しています。また、平均的に ChaSen, Juman, KAKASIより高速に動作します。 ちなみに和布蕪(めかぶ)は, 作者の好物です。 http://mecab.sourceforge.net/
だ、そうである。
で、段々記事を書くのが面倒になってきたので(備忘録のために書いているが早く開発に戻りたい。)、
そのためのスクリプトを記述する。本気で保守する気もないので全くリファクタリングもしていない。
日本語文を入力すると、それにふりがなをつけた値を返す。
一応、WebAPI化させているので、ちょっとこざかしいこともしている。
http://ymlabo.ddo.jp/~ymlab/webservice/mecab/mecab_kanji2furigana.php?str=漢字
<?php /* vim: set fdm=marker: */ $str=""; if ( count( $_REQUEST['str'] ) != 0 ) { $str = mb_convert_encoding($_REQUEST['str'],"EUC","auto"); $str = htmlspecialchars($str,ENT_QUOTES); } $from = 1;//0 is console. 1 is browser. if ( strlen($str) == 0 ) { //this is not Web service $str = $argv[1]; $str = mb_convert_encoding($str, "EUC", "auto"); if ( $argc==1 ) { print "Usage ./php mecab_kanji2furigana.php nihongobun\n"; } $from = 0; } //print "||".rawurlencode($stra)."||"; //print "str = $str | grade = $grade"; /** マルチバイト文字列を1文字ずつ配列に分割する * @see http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1417635014 * */ function mbStringToArray( $sStr, $sEnc='UTF-8'){ /**{{{*/ $aRes = array(); while($iLen = mb_strlen( $sStr, 'SJIS')) { array_push($aRes, mb_substr( $sStr, 0, 1, $sEnc)); $sStr = mb_substr( $sStr, 1, $iLen, $sEnc ); } return $aRes; } /*}}}*/ /** Mecabライブラリを走らせる.*/ function runMecab( $str ) { $ret = ""; exec ("/Users/ymlab/Sites/webservice/mecab/do_mecab.sh ". escapeshellarg($str), &$ary); //print "escapeshellarg=[".escapeshellarg($str)."]"; //exec ("/Users/ymlab/Sites/webservice/mecab/do_mecab.sh ". $str, &$ary); $isAlpha = false; //print_r($ary); foreach ( $ary as $value) { //camma check if ( $value[0] == "," ) { $kanzi = ","; $hurigana = ""; } else { $parse = explode(",", $value); $kanzi = substr($parse[0], 0, strpos($parse[0], "\t")); $hurigana = $parse[7]; } //print $parse[7];//フォーマットはこんな感じなので。[39] => 練習 名詞,サ変接続,*,*,*,*,練習,レンシュウ,レンシュー //print $kanzi; //学年でのチェックを入れることにする // if ( !mb_ereg("[あ-ん]|[ア-ン]|[0-9]", $kanzi)) { $ret .= $hurigana; // } else { /*//自分の単語が英数字の場合は、一文字スペースを入れておく。 //[そうしないと、二つ以上英単語が並んだとき、くっついてしまう.] $isUrl = false; if ( mb_ereg("[a-z]|[A-Z]|[0-9]",$kanzi )) { if ( $isAlpha == true && $isUrl == false) { $ret .= " "; } $isAlpha = true; } else { $isAlpha = false; } $ret .= $kanzi; } */ } return $ret; } /** 与えられた文字列から、該当する学年に対応したルビを振ったデータを返す * @param str 変換する文字列 * @return ret 変換された文字列 */ //function translation($str,$from, $encode='ISO-8859-1'){ /*{{{*/ function translation($str, $from, $encode='EUC-JP'){ /*{{{*/ $ret = ""; //print "I'm in translation\n"; //URLはstrに通さないように preg_match_all('/[^ -~]+|[ -~]+/', $str, $aMatches); for ( $i = 0 ;$i < count($aMatches[0]); $i++ ) { $str = $aMatches[0][$i]; //print "$str"; //漢字系でなかったら、そのままreturnする. if ( preg_match('/[ -~]+/', $str) ) { $ret .= $str; } else { $aaa = runMecab($str); $ret .= $aaa; } //print "ret=$ret<br />"; } $ret = mb_convert_kana($ret, 'KVc', mb_detect_encoding($ret, 'ASCII,JIS,UTF-8,EUC-JP,SJIS')); if ( $from == 1 ) { $ret = mb_convert_encoding($ret, "SJIS", "auto"); } print $ret; $sEnc = mb_detect_encoding($sTest, 'ASCII,JIS,UTF-8,EUC-JP,SJIS'); $a2 = mbStringToArray($sTest, $sEnc); } /**}}}*/ translation($str, $from); ?>
これで、漢字交じり文をひらがなにすることができるので、いよいよCSVファイルを落とし込もう。
適当に、このプログラムはputhurigana.php とかにしておいて、18回CSVを落とし込む。
$ php puthurigana.php 01.csv >h01.csv & $ php puthurigana.php 02.csv >h02.csv & $ php puthurigana.php 03.csv >h03.csv &
という感じ。ここ手入力の方が早そうだったので、手入力していった。
<?php if ( $argc == 1 ) { fputs(STDERR, "usage $php puthurigana.php [filename]"); exit; } $filename = $argv[1]; //fputs(STDERR,"filename = $filename\n"); $fp = @fopen( $filename, "r" ); $ret = ""; while( !feof( $fp ) ) { $row = fgets($fp, 1000); $arrayRow = explode(",", $row); //0〜1まで for ( $i=0; $i < 2; $i++ ) { $ret.= mb_convert_encoding($arrayRow[$i].",", "EUC-JP", "SJIS"); } //mecab $arrayRow[1] = mb_convert_encoding($arrayRow[1], "EUC-JP", "SJIS"); // fputs(STDERR, "arrayRow[1]=$arrayRow[1]\n"); exec("php ../mecab_kanji2furigana.php ". escapeshellarg($arrayRow[1]), &$ary ); //print_r($ary); $huriganaed = $ary[2]; $ret.= "$huriganaed,"; $ary="";//aryを初期化する. //その後の処理 for ( ;$i < count($arrayRow)-1;$i++ ) { $ret.= mb_convert_encoding($arrayRow[$i].",", "EUC-JP", "SJIS"); } $ret.= $arrayRow[$i]; //print mb_convert_encoding($row, "EUC-JP", "SJIS"); } print mb_convert_encoding($ret, "SJIS", "EUC"); fclose($fp); ?>
あとは、mecabが誤変換したところを修正していく作業をしていこう。