CentOS+PHP+WordPress+Mecab+NEologdで形態素解析を導入した


仕事で必要になったので試したらハマったし楽しかったので
備忘録とアウトプットの練習です。
お手柔らかにお願いします。

はじめに

WordPressをこよなく愛するWebエンジニア。
WordPressで作った記事を解析してタグ候補を付与する必要があり、形態素解析にたどり着きました。

正直WPのプラグインとかJQueryライブラリとかFTPにアップしてどうにかなるレベルでどうにかなってほしかった。
しかし先人の教えを探せば探すほどLinuxコマンドから逃れられない事実…

環境

CentOS6
Apache2.2
MySQL5.5
PHP5.4

インストール手順

Mecab、IPA辞書

こちらの記事を参考に難なくクリア。
【PHP】MeCabの導入手順と利用方法
エラーも発生したけどそれも記事に書かれた通りしたら大丈夫でした。

php-mecab

ハマりました

ハマり①

$ git clone https://github.com/rsky/php-mecab.git
fatal: HTTP request failed SSH

GitHubアカウントはあったので以下を参考にSSH Keyを作成

git clone 出来ない( ノД`)…おぉー!出来たー( ;∀;)!!!
お前らのSSH Keysの作り方は間違っている

Key生成時に出てくるAAみたいなやつをコピーするのかと思いましたが違いました。
FTPでファイルアクセスして中身コピーしました。

その後

$ git clone https://github.com/rsky/php-mecab.git
fatal: HTTP request failed SSH

なんでやねーん

$ git clone [email protected]:/rsky/php-mecab.git

これで通りました。

ハマり②

$ phpize
Can't find PHP headers in /usr/include/php
The php-devel package is required for use of this command.

先生の解説も虚しく、諦めて2日寝かせ、本当にわからなかったのでteratailでお世話になりました。
この場を借りて重ねてお礼申し上げます。

$ yum --disablerepo=base --enablerepo=remi install php-devel

上記コマンドでphp-develがインストールでき、そのままPHP上でMecabを動かすことができました。
これは元々のサーバーの設定のせい?のようなのであまり参考にはならないかも。

PHPでMecabを動かした

参考:PHP で Mecab を使って日本語形態素解析の結果を簡単に取得するまでの設定まとめ

$mecab = new Mecab_Tagger();//宣言
$str = get_the_content();//WPの本文を解析対象に指定
$mecab_data = array();

$nodes = $mecab->parseToNode($str);
foreach ($nodes as $n) {
    $result[] = explode(',', $n->getFeature());
}

foreach ($result as $key => $value) {
    $mecab_data[$value[0]][] = $value[6];
}

//不要な要素削除
unset($mecab_data['BOS/EOS']);
unset($mecab_data['記号']);
unset($mecab_data['助詞']);
unset($mecab_data['助動詞']);
unset($mecab_data['副詞']);
unset($mecab_data['接続詞']);

//品詞毎に単語をKeyに、出現回数をvalueに
foreach ($mecab_data as $key => $value) {
    $mecab_count[$key] = array_count_values($value);
    arsort($mecab_count[$key]);
}
foreach ($mecab_count as $key => $value) {
    foreach ($value as $k => $val) {
        if($val>2&&$k!=='*'){
            $mecab_result[$k] = $val;
        }
    }
}
arsort($mecab_result);
echo '<h3>形態素解析結果</h3><p>3回以上登場した単語</p><ul>';
foreach ($mecab_result as $key => $value) {
    echo '<li>'.$key.':'.$value.'回</li>';
}
echo '</ul>';

みたいな感じでやりました。
接続詞の"の"と名詞の"の"があったりでチューニングも必要だけどまあまあ使えるかなとは思ったんですが、
単語が分解されすぎてて固有名詞が分離してたり、英語がまるっと無視されてたので
英単語も一緒に取得できたらいいのになーなんかないかなーと思ったら

この世にないものはない

Mecab推奨の辞書が2015年で更新止まってるため新語が登録されていないので、最新の辞書が必要ならmecab-ipadic-NEologdを利用するのがよいとのこと。
ありがてえーっ!!

mecab-ipadic-NEologdインストール

公式GitHubを参考に下記コマンドを実行
コマンドにも慣れた。2週間くらいでまた嫌になる

公式以外にもこちらも参考にしました。
Mecabの拡張辞書「mecab-ipadic-neologd」を導入する手順

$ sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
$ sudo yum install mecab mecab-devel mecab-ipadic git make curl xz
$ git clone --depth 1 [email protected]:neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd

ハマり③

Step.2
以下のコマンドを実行して結果を確認する画面で「yes」と入力すると、sudo 権限で最新版がインストール(初回実行時以降は更新)されます。
$ ./bin/install-mecab-ipadic-neologd -n

チェックっぽいのは走るけど確認がでなかった。
調べるとxzの解凍ができないから?というのがあったので入れてみた。

$ sudo yum install xz xz-devel

でも動かない。
なんでかわからないけどgitをpullしたらインストールできた。xzだったのかなあ。。。
でもpullでインストールが動くっておかしない?
ここら辺はよくわからなかったです。むむむ。

$ git pull

インストールはできたみたいだけど

辞書に反映されない。
Mecabが参照している辞書がIPAのままぽい。

参照辞書を変更

Mecabのシステム辞書・ユーザ辞書の利用方法について」を導入する手順
上記を参考に/usr/local/etc/mecabrcを編集

dicdir =  /usr/local/lib/mecab/dic/ipadic
↓
dicdir =  /usr/local/lib/mecab/dic/mecab-ipadic-neologd

して、Mecabを起動

$ mecab -d /usr/local/lib/mecab/dic/neologd

これでPHPのほうにも反映されました。

NEologd辞書をPHPで動かす

取得がすごく変わった!

表題の通りWordPressの本文が解析対象なので、get_the_content()の内容を解析するんですが、
新語だけでなくIPAだとスルーされてたHTMLタグや英単語が全て解析対象になり、頻出単語がpx、paddingになりました。
スペースも全角半角分けて取得してたようでデータがとても増えました!

タグを除外するチューニングを実施


$mecab = new Mecab_Tagger();//宣言
$str = strip_tags(get_the_content());//strip_tagsでタグを除去
$mecab_data = array();

$nodes = $mecab->parseToNode($str);
foreach ($nodes as $n) {
    $result[] = explode(',', $n->getFeature());
}
foreach ($result as $key => $value) {
    if($value[6]=='*'){
        continue; //スペースなどの空要素を除外
    }else{
        $mecab_data[$value[0]][] = $value[6];
    }
}
//不要なものを削除してたら名詞だけになってた
unset($mecab_data['BOS/EOS']);
unset($mecab_data['記号']);
unset($mecab_data['助詞']);
unset($mecab_data['助動詞']);
unset($mecab_data['副詞']);
unset($mecab_data['接続詞']);
unset($mecab_data['動詞']);
unset($mecab_data['形容詞']);
unset($mecab_data['接頭詞']);

foreach ($mecab_data as $key => $value) {
    $mecab_count[$key] = array_count_values($value);
    arsort($mecab_count[$key]);
}
foreach ($mecab_count as $key => $value) {
    foreach ($value as $k => $val) {
        if($val>2&&$k!=='*'){
            $mecab_result[$k] = $val;
        }
    }
}
arsort($mecab_result);
echo '<h3>形態素解析結果</h3><p>名詞に限定し、3回以上登場した単語</p><ul>';
    foreach ($mecab_result as $key => $value) {
        echo '<li>'.$key.':'.$value.'回</li>';
    }
echo '</ul>';

解説サイトだとテレビ番組名や漫画タイトルが固有名詞として取得できる、という紹介が多かったですが、地域名や島の名前もちゃんと1単語として解析されていたので、かなり助かりました。
でもtheとかの冠詞も名詞に含まれていたりするのでチューニングは必要です。

今後の課題

辞書の更新cron

やはり魅力は辞書の更新…
cron設定をコマンドからしたことがないのでドキドキ。

取得した頻出単語をWP側でタグに設定する

この記事全然WordPress関係ないやんけ!
投稿記事や固定ページを取得して頻出単語をタグやカテゴリに設定するPHPを構築

間違い等ありましたらご指摘ください。
これからも頑張りまーす。