Go to list of users who liked
Share on X(Twitter)
Share on Facebook
More than 5 years have passed since last update.
Perl 5 Advent Calendar 2016 - Qiitaの22日目の記事です.
僕はバイト先や大学で Perl を使って自然言語処理を行う時があるのですが, 対象のテキストに記号や URL などが含まれている場合があってまー面倒です. そういった問題を解消しながら形態素解析を行うためにText::Shirasu というモジュールを使ってみましょう.
形態素解析をやってみる
もともとText::MeCab のラッパーとして開発していたものなので, Text::MeCab と似たように扱うことができます.
手始めにこのツイートを形態素解析してみましょう.
綿密に打ち合わせをしたのに突然クライアントの都合で色々変わって大変な目に合うデザイナーの図pic.twitter.com/9DnOlaf6mT
— えかきどう (@E_K_D)2016年12月18日
usestrict;usewarnings;useutf8;useData::Dumper;useText::Shirasu;my$text="綿密に打ち合わせをしたのに突然クライアントの都合で色々変わって大変な目に合うデザイナーの図 https://t.co/9DnOlaf6mT";my$ts=Text::Shirasu->new(dicdir=>"/usr/local/lib/mecab/dic/mecab-ipadic-neologd");$ts->parse($text);formy$node(@{$ts->nodes}){printf"%s\n",$node->surface;printDumper$node->feature;}実行結果は
綿密$VAR1 = [ '名詞', '形容動詞語幹', '*', '*', '*', '*', '綿密', 'メンミツ', 'メンミツ' ];に$VAR1 = [ '助詞', '副詞化', '*', '*', '*', '*', 'に', 'ニ', 'ニ' ];打ち合わせ$VAR1 = [ '名詞', '一般', '*', '*', '*', '*', '打ち合わせ', 'ウチアワセ', 'ウチアワセ' ];...とこんな感じで出力されます.
Text::Shirasu のnew() を呼び出す時 Text::MeCab と同じ引数を渡すことができます. ここではmecab-ipadic-neologd を使用するため引数でそのパスを指定しています.
また, Text::MeCab と違って, feature が配列リファレンスの状態で格納されています. これは Text::Shirasu の parse メソッドを実行した時, Text::MeCab でパースした結果を加工して保存しているからです.
ある品詞だけを抜き出す
例えば名詞だけ抜きだしたい場合があるとします. その場合先ほどのコードに 1 行コードを加えるだけで品詞のフィルタリングを行うことができます.
usestrict;usewarnings;useutf8;useData::Dumper;useText::Shirasu;my$text="綿密に打ち合わせをしたのに突然クライアントの都合で色々変わって大変な目に合うデザイナーの図 https://t.co/9DnOlaf6mT";my$ts=Text::Shirasu->new(dicdir=>"/usr/local/lib/mecab/dic/mecab-ipadic-neologd");$ts->parse($text);# この 1 行を追加$ts->filter(type=>[qw/名詞/]);formy$node(@{$ts->nodes}){printf"%s\n",$node->surface;printDumper$node->feature;}結果は
綿密$VAR1 = [ '名詞', '形容動詞語幹', '*', '*', '*', '*', '綿密', 'メンミツ', 'メンミツ' ];打ち合わせ$VAR1 = [ '名詞', '一般', '*', '*', '*', '*', '打ち合わせ', 'ウチアワセ', 'ウチアワセ' ];...ちゃんと名詞のみ抜き出すことができているかと思います. さらに名詞の中でも一般, 固有名詞など様々な種類があります. それらも合わせて抜きだしたい場合, 先ほど加えた 1 行を次のように変更してみましょう.
$ts->filter(type => [qw/名詞/], 名詞 => [qw/固有名詞/]);実行してみると
クライアント$VAR1 = [ '名詞', '固有名詞', '人名', '一般', '*', '*', 'CLIENT', 'クライアント', 'クライアント' ];https$VAR1 = [ '名詞', '固有名詞', '一般', '*', '*', '*', 'HTTPS', 'エイチティーティーピーエス', 'エイチティーティーピーエス' ];...という感じに名詞の固有名詞のみ抜き出されます。
テキストの正規化を行う
形態素解析を行う前に, 始めの方で例に挙げた要らない文字列を削除するためにテキストの正規化を行います. 例えば次のような文章があったとしましょう.
明日は~祝日だからーーピースフル★【天皇誕生日】
ここで星とカッコ内の文字列も削除したいですね!!
そこでnormalize メソッドを使いましょう!!
usestrict;usewarnings;useutf8;useData::Dumper;useText::Shirasu;my$text="明日は~祝日だからピーーースフル★【天皇誕生日】";my$ts=Text::Shirasu->new(dicdir=>"/usr/local/lib/mecab/dic/mecab-ipadic-neologd");$ts->parse($text);formy$node(@{$ts->nodes}){printf"%s\n",$node->surface;}今のままだと
明日は~祝日だからピーーースフル★【天皇誕生日】ですので、正規化に挑戦しましょう。
Text::Shirasu には「ー」を正規化するサブルーチンが含まれていますのでそれも利用しましょう.
usestrict;usewarnings;useutf8;useData::Dumper;useText::Shirasuqw/normalize_hyphen/;my$text="明日は~祝日だからピーーースフル★【天皇誕生日】";my$ts=Text::Shirasu->new(dicdir=>"/usr/local/lib/mecab/dic/mecab-ipadic-neologd");my$n=$ts->normalize($text,\&normalize_hyphen,\&normalize_star_brackets);$ts->parse($n);formy$node(@{$ts->nodes}){printf"%s\n",$node->surface;}subnormalize_star_brackets{local$_=shift;s/(★|【.*】)//g;$_;}ここでnormalize_star_brackets という ★ と 【天皇誕生日】 を取り除くためのサブルーチンを定義しました. そしてこれとnormalize_hyphen をnormalize メソッドの引数で与えます. 詳しい使い方はここで確認できます.
このコードを実行すると,
明日は祝日だからピースフルという結果を得ることができます!!
最後に
このモジュールのリポジトリはgithub.com/Code-Hex/Text-Shirasu です.
改善点がありましたら気軽に Pull Request を送ってください!
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme