MecabとLingua::JA::Summarizeで文章のキーワード抽出をCakePHPで

2008.11.12 / php

文章中のキーワード抽出を行いたくなっていろいろ調べていて、次の組み合わせで実現することができました。

  • Mecab
  • Lingua::JA::Summarize
  • Pecl/Perl

Mecabは文書の形態素解析に。Lingua::JA::Summarizeはサイボウズラボ奥さんのキーワード抽出CPANモジュール。これをCakePHPに組み込みたかったのでPeclのPerlライブラリ(PHPからPerlのコードをダイレクトに呼べる)。導入も特に難しくないので、その導入メモを残しておきます。

Mecab

Fedora系Linuxだとyumで辞書ファイルも一緒にさっくりインストールできます。Perlのモジュールも入れておきます。

  sudo yum -y install mecab\*
  sudo yum -y install perl-mecab\*
  

Lingua::JA::Summarize

CPANからインストールできるのですが、僕の環境だとテストでエラーになるのでforce installします。あと、実行時エラーも出たので、次のようにインストールすると回避できました。あらかじめ

  alias cpan='perl -MCPAN -e shell'
  

と、しています。

  sudo cpan
  install HTML::Strip
  install Jcode
  install Class::ErrorHandler
  force install Lingua::JA::Summarize
  

Pecl/Perl

これもpeclコマンドでOKです。あらかじめ次のものをインストールしておいたほうがいいかも。2行目の「sudo yum -y install perl-\*」はちょっと強引すぎる気が自分でもしてるのですが、何かしらのperl系モジュールがないとpecl/perlのインストールにコケてしまったことは確か。(このあたりの詳細のメモを失念。。。)

  sudo yum -y install php-devel
  sudo yum -y install perl-\*
  

この上で

  sudo pecl install pecl/perl
  

また、extensionにperl.soを登録します。

  sudo vi /etc/php.d/perl.ini
  

で、次の1行を追加。

  extension=perl.so
  

これで、Apacheを再起動するとPHPでキーワード抽出が可能になります。

CakePHPに設置

app/vendors にLingua/JA/ディレクトリを作成し、そこにSummarize.phpを作成します。

Summarize.php

  <?php
  class Summarize{
      
      private $summarize;
      
      public function __construct(){
          
          $perl = new Perl();
          $perl->eval('use HTML::Strip;');
          $perl->eval('use Lingua::JA::Summarize;');
          
          $this->summarize = new Perl ("Lingua::JA::Summarize", "new",
              array(
                  "charset" => 'utf8',
                  "mecab_charset" => 'utf8',
                  "default_cost" => 2.5,
                  "singlechar_factor" => 0.2
                  )
              );
      }
      
      function getKeyword($key, $maxNum=15){
          $this->summarize->analyze($key);
          return $this->summarize->array->keywords(
              array(
                  "threshold" => 5,
                  "minwords"  => 1,
                  "maxwords"  => $maxNum
              )
          );
      }
  }
  ?>
  

これをapp/config/bootsrrap.phpで読み込ませます。次の1行を最後に追加。

  App::import( 'Vendor', 'Summarize' , array('file'=>'Lingua' . DS . 'JA'  . DS . 'Summarize.php'));
  

これでキーワード抽出用のモジュールSummarizeが読み込まれるので、たとえばControllerで次のような処理を行うことができます。

  $summarize = new Summarize();
  $keys = $summarize->getKeyword($word, $num);
  

$wordは抽出対象の文章、$numは抽出キーワード数です。$keysは抽出されたキーワードの配列が返ります。返ってくるキーワードの抽出に違和感があれば、Summarize.phpのdefault_cost、singlechar_factorあたりをチューニングしてみましょう。このあたりのパラメータについては奥さんのドキュメントが最も分かりやすくまとまっていると思います。