DEVELOPERS BLOGデベロッパーズブログ

  1. HOME > 
  2. 加藤 正人のデベロッパーズブログ > 
  3. 形態素解析システム MeCab (めかぶ) を CakePHP から利用する

加藤 正人のデベロッパーズブログ

加藤 正人

氏名
加藤 正人
役職
多分SE
血液型
秘密
出没
美味しいもののあるところ
特色
タヒチ大好き。ちょいメタボ。

加藤 正人

2015/05/09

形態素解析システム MeCab (めかぶ) を CakePHP から利用する

 

先の記事で形態素解析システム MeCab (めかぶ) を導入したのだが、それだけではつまらないので管理者権限なしで (module 等にすることなく) CakePHP から利用する方法を考えてみた。

実装方法

具体的にはコンポーネントとして実装し、MeCab 呼び出しは mecab コマンドを子プロセスとして実行し結果を受け取る方法とする。

コンポーネントのオプションとして、以下のものを用意する。

mecab_path

MeCab の実行ファイル mecab を指すフルパス文字列。省略不可

remove_spaces

mecab への入力文字列から空白を事前に除去するかどうかを指定する論理値。偽の場合は除去しない。それ以外の場合は除去する。省略時の既定値は TRUE。

spawn_type

mecab 処理の子プロセスをどのように生成するかを指定する文字列。利用可能な文字列とその意味は下記の通り。省略時の既定値は exec

proc_open

子プロセスを PHP の proc_open 関数を使用して生成する。子プロセスの入出力はともにパイプで行われ、オーバーヘッドが最も小さいが、デッドロックした場合 web サーバもロックされる恐れがある。web サーバがデッドロックに陥った場合は、サービスを再起動する必要がある。共用サーバ等では使用が禁止されていることもある。

exec

子プロセスを PHP の exec 関数を使用して生成する。子プロセスへの入力 (mecab で処理する入力文) は tempnam() 関数で名前生成した一時ファイルに保存してコマンドラインのパイプで mecab 処理に渡される。mecab 処理結果は exec() 関数の参照渡し変数に格納される。proc_open が利用できない (または禁止されている) サーバの場合でも、exec() の利用ができるのであればこちらを使用する。

result_type

mecab 処理結果をどのように取得するかを指定する文字列。指定可能な文字列とその意味は下記の通り。省略時の既定値は raw

raw

mecab の処理結果をそのまま文字列として返す。

'すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
EOS'
array

mecab の処理結果の形態素情報を連想配列で表現し、それらを要素に持つ配列として返す。

array(
	(int) 0 => array(
		'表層形' => 'すもも',
		'品詞' => '名詞',
		'品詞細分類1' => '一般',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'すもも',
		'読み' => 'スモモ',
		'発音' => 'スモモ'
	),
	(int) 1 => array(
		'表層形' => 'も',
		'品詞' => '助詞',
		'品詞細分類1' => '係助詞',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'も',
		'読み' => 'モ',
		'発音' => 'モ'
	),
	(int) 2 => array(
		'表層形' => 'もも',
		'品詞' => '名詞',
		'品詞細分類1' => '一般',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'もも',
		'読み' => 'モモ',
		'発音' => 'モモ'
	),
	(int) 3 => array(
		'表層形' => 'も',
		'品詞' => '助詞',
		'品詞細分類1' => '係助詞',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'も',
		'読み' => 'モ',
		'発音' => 'モ'
	),
	(int) 4 => array(
		'表層形' => 'もも',
		'品詞' => '名詞',
		'品詞細分類1' => '一般',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'もも',
		'読み' => 'モモ',
		'発音' => 'モモ'
	),
	(int) 5 => array(
		'表層形' => 'は',
		'品詞' => '助詞',
		'品詞細分類1' => '係助詞',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'は',
		'読み' => 'ハ',
		'発音' => 'ワ'
	),
	(int) 6 => array(
		'表層形' => 'もも',
		'品詞' => '名詞',
		'品詞細分類1' => '一般',
		'品詞細分類2' => '*',
		'品詞細分類3' => '*',
		'活用形' => '*',
		'活用型' => '*',
		'原型' => 'もも',
		'読み' => 'モモ',
		'発音' => 'モモ'
	)
)
object

mecab の処理結果の形態素情報を stdClass オブジェクトで表現し、それらを要素に持つ配列として返す。

array(
	(int) 0 => object(stdClass) {
		表層形 => 'すもも'
		品詞 => '名詞'
		品詞細分類1 => '一般'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'すもも'
		読み => 'スモモ'
		発音 => 'スモモ'
	},
	(int) 1 => object(stdClass) {
		表層形 => 'も'
		品詞 => '助詞'
		品詞細分類1 => '係助詞'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'も'
		読み => 'モ'
		発音 => 'モ'
	},
	(int) 2 => object(stdClass) {
		表層形 => 'もも'
		品詞 => '名詞'
		品詞細分類1 => '一般'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'もも'
		読み => 'モモ'
		発音 => 'モモ'
	},
	(int) 3 => object(stdClass) {
		表層形 => 'も'
		品詞 => '助詞'
		品詞細分類1 => '係助詞'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'も'
		読み => 'モ'
		発音 => 'モ'
	},
	(int) 4 => object(stdClass) {
		表層形 => 'もも'
		品詞 => '名詞'
		品詞細分類1 => '一般'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'もも'
		読み => 'モモ'
		発音 => 'モモ'
	},
	(int) 5 => object(stdClass) {
		表層形 => 'は'
		品詞 => '助詞'
		品詞細分類1 => '係助詞'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'は'
		読み => 'ハ'
		発音 => 'ワ'
	},
	(int) 6 => object(stdClass) {
		表層形 => 'もも'
		品詞 => '名詞'
		品詞細分類1 => '一般'
		品詞細分類2 => '*'
		品詞細分類3 => '*'
		活用形 => '*'
		活用型 => '*'
		原型 => 'もも'
		読み => 'モモ'
		発音 => 'モモ'
	}
)

なお、mecab コマンドには標準辞書以外の辞書指定や出力項目のチューニング機能等もあるが、これらは実装していない。

コンポーネントの宣言

CakePHP のコントローラ内で、下記のようにする。(この例では、LambdaTools プラグインのコンポーネントとして実装している)

なお、コンポーネントの設定はアクション内で MeCab::setOption() メソッドで設定することも可能。

パブリックメソッド

MeCab コンポーネントには以下のパブリックメソッドが用意されている。

analyze($text)

$text に与えられた日本語文字列を形態素解析した結果を返す。解析結果の形式はコンポーネントの 'result_type' オプションに従う。

setOptions($options)

連想配列として指定された MeCab コンポーネントオプションを設定する。連想配列は {オプション名} => {値} となる。このメソッドを使うことで、アクション処理時に MeCab コンポーネントの動作を変更することができる。

以下の簡単なサンプルは、入力フォームで入力テキストと解析結果のタイプを読み込み、テキストを mecab で処理して結果を配列で表示させるアクションの例である。(他のオプションはコンポーネント宣言時に与えているとする。)

コンポーネントのコード

最後に、MeCab コンポーネントのソースを示す。

以上。

関連タグ: CakePHP2  MeCab  めかぶ  全文検索 

関連エントリー

CakePHP のレンダリング結果を保存したい

CakePHP 2.x の Cookie と js.cookie.js

時刻入力用 jQuery Plugin TimePicki の不具合調整

CakePHP プラグインで HTTPS 判定

作業用モデルビヘイビア

CakePHP のバリデーション時に状況に応じてバリデーションルールを変更する

CsvLoader ビヘイビアを使って CSV を一発でロードする Cake Shell

CakePHP の Security コンポーネント、ベーシック認証、CGI

共用サーバに MeCab をインストールする

Google APIs Client Library を CakePHP から利用する

分数電卓を作ってみる・その2

分数電卓を作ってみる・その1

CsvLoaderBhavior - CSV データを CakePHP で扱うための一手法・その2

 CsvLoaderBhavior - CSV データを CakePHP で扱うための一手法

CakePHP でストアドファンクション

テキストフィールドを CSV として処理する CakePHP ビヘイビア・補足

テキストフィールドを CSV として処理する CakePHP ビヘイビア・その2

テキストフィールドを CSV として処理する CakePHP ビヘイビア・その1

Google Maps で郵便番号⇒住所変換・その2

テキストを自動整形する簡易 CakePHP ヘルパー

Google Chart へのアクセスをヘルパーで実装してみる【その2】

Google Chart へのアクセスをヘルパーで実装してみる【その1】

Google reCAPTCHA を使いやすくする

駅データ.jp のデータを CakePHP から使う

CakePHP の小ネタ

UploadPack を Exif Orientation 対応にする

作業用テーブル処理を再利用可能なツール化してみる・その1

クリックイベントが2回実行される?!

CakePHP のフォームで required・その2

CakePHP の Paginator の sort() で昇順ソート時に NULL 値を最後にしたい

CakePHP のフォームで required

UploadPack のヘルパーメソッド名称が変わっていた

CakePHP 2.x の PaginatorHelper::sort の不思議

CakePHP で四苦八苦 - あるフィールドにだけ値が書き込まれない

UploadPack で四苦Hack その後

CakePHP の小ネタ

CakePHP v2 のエラー処理

IE10 と CKEditor

2013/03/23
IE10 と CKEditor

UploadPack で四苦Hack・その2

Paginator で見かけの URL を使用する方法

「Notes プラグインが見つかりません」

CakePHP v2 で HTTP エラー画面をカスタマイズする

UploadPack で四苦Hack

PHP 5.4 と CakePHP 2.x