work.log

元エンジニアの備忘録的ブログ

MeCabで漢字が混在する文字を50音順に分類する

投稿:

MeCab を使って漢字が混在した文字を50音順に分類するメモです。

漢字が混在する人名を50音順に並べたいという事で MeCab を使って人名索引データを作成する事にしました。

例えば「山田太郎」なら「や」、「George Soros」なら「G」をそれぞれ人名索引用データとして取得します。

ひらがな、カタカナ、ローマ字だけなら MeCab は不要ですが、漢字が含まれるとソートが期待通り動かないのでこの部分を MeCab で処理します。50音とか言っていますがローマ字はそのまま抜き出す仕様です。

あと、Perl を使って書いてます。

という事で、まずは環境構築から。

環境構築

動作確認をした環境は下記のような感じです。

  • CentOS 6.8
  • Perl v5.10.1
  • MeCab 0.996
  • Text::MeCab
  • Lingua::JA::Regular::Unicode

Perl は CentOS に標準インストールされたバージョンをそのまま使ってます。

MeCab のインストール

MeCab は yum からインストール方法もありますが、Text::MeCab をインストールする時に mecab-config が無いと言われたのでソースから入れました。

とりあえず最新版を取ってくれば良いと思うので下記からダウンロードしてきます。

サーバの適当なディレクトリにアップしたら下記手順でインストールします。

# tar xfz mecab-0.996.tar.gz
# cd mecab-0.996
# ./configure --with-charset=utf8
# make && make install
# cd ..

# tar xfz mecab-ipadic-2.7.0-20070801.tar.gz
# cd mecab-ipadic-2.7.0-20070801
# ./configure --with-charset=utf8
# make && make install

Text::MeCab のインストール

Perl モジュール Text::MeCab は cpan からインストールします。

普通にインストールしようとするとコケるので force をつけて無理やりインストールします。

# perl -MCPAN -e shell
> force install Text::MeCab

Lingua::JA::Regular::Unicode のインストール

Lingua::JA::Regular::Unicode は全角文字を半角文字に変換したり、カタカナをひらがなに変換したりする Perl モジュールです。

これも cpan からインストールしますが、Module::Build, YAML モジュールが無くてコケたので先にインストールします。

# yum -y install perl-YAML
# perl -MCPAN -e shell
> install Module::Build
> install Lingua::JA::Regular::Unicode

これで準備が整いました。

Mecab の判定処理

本題の漢字混じりの文字から索引データを取得する処理です。

とりあえずコードがこれ。

#!/usr/bin/perl

use strict;
use warnings;
use Encode;
use Text::MeCab;
use Lingua::JA::Regular::Unicode qw/alnum_z2h hiragana2katakana katakana2hiragana/;

    my $utf8 = find_encoding 'utf8';
    my $str = $ARGV[0] || exit;;

    my $initial = &mecab_initial($str);

    print "$str => $initial\n";

sub mecab_initial {

    my $word = shift || return(0);

    $word = $utf8->decode($word);

    # 全角ローマ字を半角ローマ字へ変換 (A -> A)
    $word = alnum_z2h($word);

    $word = $utf8->encode($word);

    # 判定除外の文字は「その他」に分類 (数字、記号等)
    if ($word =~ /^(\s|\d| |\(|\)|\[|\]|,|\.|\?|\!|\$|\&|\#|\"|\'|、|。)/) {
        return('その他');
    }

    # 漢字の処理
    if ($word !~ /^[ぁ-んァ-ンa-zA-Z]/) {

        my $mecab = Text::MeCab->new();
        my $node = $mecab->parse($word);

        while ($node->surface) {

            # feature の中身 -> "名詞,固有名詞,人名,姓,*,*,山田,ヤマダ,ヤマダ"
            my @features = split(',', $node->feature);
            if (!$features[7]) { return('その他'); }
 
            # 「ヤマダ」を取得
            $word = $features[7];

            $node = $node->next;
            last;

        }

    }

    # 1文字切り取る (マルチバイト文字対応)
    $word = &mb_substr($word, 1);

    $word = $utf8->decode($word);

    # カタカナをひらがなへ
    $word = katakana2hiragana($word);

    # 小文字を大文字へ
    $word =~ tr/a-z/A-Z/;

    $word = $utf8->encode($word);

    return($word);

}

sub mb_substr {

    my ($str, $crop) = @_;

    if (!$str) { return(0); }

    $str = $utf8->decode($str);

    if (length($str) > $crop) {
        $str = substr($str, 0, $crop );
    }

    $str = $utf8->encode($str);
    return($str);

}
exit;

ポイントは MeCab の処理よりも全角を半角に変換したり、カタカナをひらがなに変換したりという所だと思う。

Lingua::JA::Regular::Unicode はこの辺りの事が簡単に出来るので便利です。

これを実行するとこんな結果になります。

# perl mecab.pl 山田太郎
山田太郎 => や

# perl mecab.pl やまだたろう
やまだたろう => や

# perl mecab.pl ヤマダタロウ
ヤマダタロウ => や

# perl mecab.pl YamadaTaro
YamadaTaro => Y

うまく出来ました。

大体の名前は IPA の辞書を使うだけでも変換出来ますが、ちょっと特殊な読み方をする名前やキラキラネームとかは流石に無理なのでその場合は辞書のカスタマイズで対応します。

これで人名索引データの作成は以上です。