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

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

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

加藤 正人

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

PhpSpreadsheet でExcel ファイルを読み込む (CakePHP3)

2015/05/09

PhpSpreadsheet でExcel ファイルを読み込む (CakePHP3)

 

先の記事で形態素解析システム 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  めかぶ  全文検索