Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

「魔法少女まどか☆マギカ」の台詞をNLTK(Natural Language Toolkit)で解析する

目次

  1. 魔法少女まどか☆マギカ
  2. NLTK
  3. NLTKコーパス
  4. まど☆マギ台詞単語解析
  5. まど☆マギ台詞形態素解析

魔法少女まどか☆マギカ


NLTK練習の題材として2011年の大ヒットアニメ?「魔法少女まどか☆マギカ」の台詞を用いる。通称まど☆マギで知られる本作品であるが、第15回文化庁メディア芸術祭アニメーション部門大賞、既に映画かも決まっておりテレビシリーズの総集編前後編と完全新作の全3作品の製作が予定されている。いわゆるダークファンタジーの世界観で台詞の中にも絶望を彷彿させるマイナス思考な台詞が多いように思う。事前の予想では「いやだ」とか「助けて」などの台詞が頻繁に使われていると考えたが、それらをNLTKを用いて検証してみる。この記事の前半はNLTKの設定、後半がまど☆マギの台詞を単語/形態素の両面で解析している。尚使用するサンプルコードは全てgithubに挙げているので、そちらを参照して欲しい。https://github.com/yutakikuchi/NLTK/tree/master/madmagi

NLTK

NLTKとは
  • NLTKとはNatural Language Toolkitの略。
  • Pythonで書かれた自然言語処理ToolKit。テキストマイニング等が可能。
  • Windows/MacOS/Linux上で動作させる事ができる。
  • Linuxの場合Python2.4x,2.5x,2.6xを必要とする。
  • インストールする際にはPyAMLが必要で、解析結果をグラフ化するようにNumPyやmatplotlibを一緒に使うと良い。
NLTKのインストール
  • http://www.nltk.org/download 公式ドキュメントに書いてある内容を実行する。尚今回のインストール実行環境はCentOS release 5.7 (Final)とする。
  • 始めに入れておくと後で嵌らないpkgは次のもの
$ sudo yum install gcc-c++ kernel-devel ncurses-devel glibc glibc-devel  glib-devel glib2-devel gtk2-devel tk tk-devel tcl tcl-devel tkinter freetype freetype-devel libpng libpng-devel
Pythonのversion確認
  • pythonのversionが2.4x <= python <= 2.6xとなっていなければpythonのインストールを行う必要がある。
$ python -V
Python 2.4.3
PyYAML install
$ wget 'http://pyyaml.org/download/pyyaml/PyYAML-3.09.tar.gz'
$ tar -xzf PyYAML-3.09.tar.gz
$ cd PyYAML-3.09
$ sudo python setup.py install
NLTK install
$ wget 'http://nltk.googlecode.com/files/nltk-2.0.1rc1.tar.gz'
$ tar -xzf nltk-2.0.1rc1.tar.gz
$ cd nltk-2.0.1rc1
$ sudo python setup.py install
numpy install
$ wget 'http://prdownloads.sourceforge.net/numpy/numpy-1.5.1.tar.gz'
$ tar -xzf numpy-1.5.1.tar.gz
$ cd numpy-1.5.1
$ sudo python setup.py install

SystemError: Cannot compile 'Python.h'. Perhaps you need to install python-dev|python-devel.と怒られてしまうので、python-develを入れる。python-develのインストール完了後にサイドnumpyをインストールする。

python-devel install
$ sudo yum install python-devel
matplotlib install
$ wget 'http://prdownloads.sourceforge.net/matplotlib/matplotlib-1.0.1.tar.gz'
$ tar -xzf matplotlib-1.0.1.tar.gz
$ cd matplotlib-1.0.1
$ sudo python setup.py install

ft2build.h: そのようなファイルやディレクトリはありませ/png.h: そのようなファイルやディレクトリはありませんとインストール中に怒られるので、freetype-devel,freetype,libpng,libpng-develを入れる。インストル後再度matplotlibを入れる。

freetype/freetype-devel install
$ yum install freetype freetype-devel libpng libpng-devel
MeCabのinstall
$ wget http://mecab.googlecode.com/files/mecab-0.99.tar.gz
$ tar -xzf mecab-0.99.tar.gz
$ cd mecab-0.99
$ ./configure --with-charset=utf8
$ make && sudo make install
mecab-ipadicのinstall
$ wget http://sourceforge.net/projects/mecab/files/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz/download
$ tar -xzf mecab-ipadic-2.7.0-20070801.tar.gz
$ ./configure --with-charset=utf8
$ make && sudo make install
mecab-pythonのinstall
$ wget http://sourceforge.net/projects/mecab/files/mecab-python/0.99/mecab-python-0.989.tar.gz/download
$ tar -xzf mecab-python-0.99.tar.gz
$ python setup.py build
$ sudo python setup.py install
mecab-pythonの起動
$ Python 2.6.6 (r266:84292, Dec 25 2011, 11:27:19) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MeCab
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "MeCab.py", line 25, in <module>
    _MeCab = swig_import_helper()
  File "MeCab.py", line 17, in swig_import_helper
    import _MeCab
ImportError: libmecab.so.2: cannot open shared object file: No such file or directory
  • エラーが出てしまう。原因はlibmecab.so.2のファイルが/usr/local/lib/libmecab.so.2のパスに設置されているからlibとして読み込めていない。
  • このエラーを解決するためには/etc/ld.so.conf.d/lib.confというファイルを作成して以下の一行を加える。
/usr/local/lib
  • 設定の内容を反映するにはldconfigコマンドを実行する。
$ sudo ldconfig
swigのinstall
  • JUMANで必要なswigを先に入れておく。
$ wget 'http://prdownloads.sourceforge.net/swig/swig-2.0.0.tar.gz'
$ tar -xzf swig-2.0.0.tar.gz
$ cd swig-2.0.0
$ ./configure --prefix=/usr/local/swig-py26/ --with-python=/usr/local/bin/python2.6
$ make && sudo make install 
JUMAN/cJumanのinstall
$ wget 'http://nlp.ist.i.kyoto-u.ac.jp/DLcounter/lime.cgi?down=http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/juman/juman-6.0.tar.gz&name=juman-6.0.tar.gz'
$ tar -xzf juman-6.0.tar.gz
$ cd juman-6.0
$ CFLAGS=-fPIC ./configure
$ make && sudo make install
$ cd lib
$ wget 'http://app-dist.khlog.net/software/python-cjuman/cJuman.i'
$ /usr/local/swig-py26/bin/swig -python cJuman.i
$ gcc -c cJuman_wrap.c -fPIC -I/usr/local/include/python2.6
$ gcc -shared *.o -o _cJuman.so
$ sudo install -m 644  _cJuman.so cJuman.py /usr/local/lib/python2.6/site-packages/

NLTKコーパス

代表的なコーパスの種類
NLTKでのコーパスダウンロード
$ python
Python 2.6.6 (r266:84292, Dec 25 2011, 11:27:19) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import nltk
>>> nltk.download()
NLTK Downloader
---------------------------------------------------------------------------
    d) Download      l) List      c) Config      h) Help      q) Quit
---------------------------------------------------------------------------
Downloader> d
Download which package (l=list; x=cancel)?
  Identifier> knbc
  usr/local/lib/python2.6/site-packages/nltk/__init__.py:658: DeprecationWarning: object.__new__() takes no parameters
    Downloading package 'knbc' to /home/yuta/nltk_data...
KNBファイルデータ
  • 以下のコマンドで中身を見てみる。
$ nkf corpora/knbc/corpus1/KN001_Keitai_1/KN001_Keitai_1-1-1-01
  • 結果
# S-ID:KN001_Keitai_1-1-1-01 KNP:2008/02/25 SCORE:-12.47259 MOD:2009/02/01
* 1D <BGH:携帯/けいたい><文節内><係:文節内><文頭><サ変><括弧始><引用内文頭><体言><名詞項候補><先行詞候補><非用言格解析:動><態:未定><正規化代表表記:携帯/けいたい><C用;【不特定:人】;ガ;-1;-1;9.999:(文外)><C用;【電話】;ヲ;0;1;9.999:KN001_Keitai_1-1-1-01(同一文):1タグ>
[ [ [ 特殊 1 括弧始 3 * 0 * 0 NIL <文頭><記英数カ><英記号><記号><括弧始><括弧><接頭><非独立接頭辞><タグ単位始><文節始>
携帯 けいたい 携帯 名詞 6 サ変名詞 2 * 0 * 0 "カテゴリ:人工物-その他:抽象物 ドメイン:家庭・暮らし 代表表記:携帯/けいたい" <カテゴリ:人工物-その他:抽象物><ドメイン:家庭・暮らし><代表表記:携帯/けいたい><正規化代表表記:携帯/けいたい><漢字><かな漢字><名詞相当語><サ変><自立><内容語><意味有>
+ 5D <BGH:電話/でんわ><文節内><係:文節内><補文ト><サ変><括弧終><引用内文末><体言><名詞項候補><先行詞候補><非用言格解析:動><態:未定><正規化代表表記:電話/でんわ><C用;【携帯】;修飾;0;0;9.999:KN001_Keitai_1-1-1-01(同一文):0タグ>
電話 でんわ 電話 名詞 6 サ変名詞 2 * 0 * 0 "補文ト カテゴリ:人工物-その他 ドメイン:家庭・暮らし 代表表記:電話/でんわ" <補文ト><カテゴリ:人工物-その他><ドメイン:家庭・暮らし><代表表記:電話/でんわ><正規化代表表記:電話/でんわ><漢字><かな漢字><名詞相当語><サ変><自立><複合←><内容語><意味有><タグ単位始>
] ] ] 特殊 1 括弧終 4 * 0 * 0 NIL <記英数カ><英記号><記号><括弧終><括弧><述語区切><付属><複合←>
* 3D <文節内><係:文節内><サ変><体言><名詞項候補><先行詞候補><非用言格解析:動><態:未定><正規化代表表記:プリペイドカード/プリペイドカード>
KNBの単語ごとの出力
  • KNBのタグ付けデータを単語ごとに出力する。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys 
reload(sys)
sys.setdefaultencoding('utf-8')

import re,pprint,nltk
from nltk.corpus.reader import *
from nltk.corpus.reader.util import *
from nltk.corpus.util import *
from nltk.text import Text

def pp(obj):
    pp = pprint.PrettyPrinter(indent=4, width=160)
    str = pp.pformat(obj)
    return re.sub(r"\\u([0-9a-f]{4})", lambda x: unichr(int("0x"+x.group(1),16)), str)

def _knbc_fileids_sort(x):
    cells = x.split('-')
    return (cells[0], int(cells[1]), int(cells[2]), int(cells[3]))

root = nltk.data.find('corpora/knbc/corpus1')
fileids = [f for f in find_corpus_fileids(FileSystemPathPointer(root), ".*") if re.search(r"\d\-\d\-[\d]+\-[\d]+", f)] 
knbc = LazyCorpusLoader('knbc/corpus1', KNBCorpusReader, sorted(fileids, key=_knbc_fileids_sort), encoding='euc-jp')
print '/'.join( knbc.words()[:100] )
  • 結果
[/携帯/電話/]/プリペイド/カード/携帯/布教/。/もはや/’/今さら/’/だ/が/、/と/いう/接頭句/で/始める/しか/ない/ほど/今さら/だ/が/、/私/は/プリペイド/携帯/を/ずっと/使って/いる/。/犯罪/に/用い/られる/など/に/より/かなり/イメージ/を/悪化/さ/せて/しまった/プリペイド/携帯/だ/が/、/一/ユーザー/と/して/は/、/かなり/使いで/が/ある/。/かつて/は/このような/話/を/友人/に/振って/も/、/「/携帯/電話/の/料金/は/親/が/払って/いる/から/別に/.../」/と/いう/にべもない/答え/が/返って/くる/ばかりだった/が
(布教/。
係り受け関係を表現した木構造
  • 係り受け関係を表現した木構造にアクセスするには上のコードに以下の内容を追加する。
print '\n\n'.join( '%s' % tree for tree in knbc.parsed_sents()[0:2] )
  • 結果
  (電話/] [/携帯)
  (携帯 (カード プリペイド)))

(使って/いる/。
  (今さら/だ/が/、
    (ほど
      (始める/しか/ない
        もはや
        (接頭句/で (いう ’/今さら/’/だ/が/、/と)))))
  私/は
  (携帯/を プリペイド)
  ずっと)
単語と品詞のタプルを表示する
  • 以下を上のコードに追加する
print '\n'.join( ' '.join("%s/%s"%(w[0], w[1].split(' ')[2]) for w in sent) for sent in knbc.tagged_sents()[0:20] )
  • 結果
[/特殊 携帯/名詞 電話/名詞 ]/特殊 プリペイド/名詞 カード/名詞 携帯/名詞 布教/名詞 。/特殊
もはや/副詞 ’/特殊 今さら/副詞 ’/特殊 だ/判定詞 が/助詞 、/特殊 と/助詞 いう/動詞 接頭句/名詞 で/助詞 始める/動詞 しか/助詞 ない/形容詞 ほど/名詞 今さら/副詞 だ/判定詞 が/助詞 、/特殊 私/名詞 は/助詞 プリペイド/名詞 携帯/名詞 を/助詞 ずっと/副詞 使って/動詞 いる/接尾辞 。/特殊

まどか☆マギカの台詞をスクレイピング

NLTKの設定の説明が長過ぎたが、以下からがこの記事の本題。

台詞
Pythonスクレイピングコード
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys,re,urllib,urllib2
urls = ( 'http://www22.atwiki.jp/madoka-magica/pages/170.html', 
         'http://www22.atwiki.jp/madoka-magica/pages/175.html',
         'http://www22.atwiki.jp/madoka-magica/pages/179.html',
         'http://www22.atwiki.jp/madoka-magica/pages/180.html',
         'http://www22.atwiki.jp/madoka-magica/pages/200.html',
         )
f = open( './madmagi.txt', 'w' )
opener = urllib2.build_opener()
ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1 Safari/    534.51.22'
referer = 'http://www22.atwiki.jp/madoka-magica/'
opener.addheaders = [( 'User-Agent', ua ),( 'Referer', referer )]
for url in urls:
    content = opener.open( url ).read()
    if re.compile( r'<div class="contents".*?>((.|\n)*?)</div>', re.M ).search( content ) is not None:
        data = re.compile( r'<div class="contents".*?>((.|\n)*?)</div>', re.M ).search( content ).group()
        if re.compile( r'「(.*?)」', re.M ).search( data ) is not None: 
            lines = re.compile( r'「(.*?)」', re.M ).findall( data )
            for line in lines:
                f.write( line + "\n" )
f.close()
抽出サンプル
  • 抽出したデータを後で利用するためmadmagi.txtとして保存する。
んっん…あっ…!
あっ…!
ひどい…
仕方ないよ。彼女一人では荷が重すぎた
でも、彼女も覚悟の上だろう
そんな…あんまりだよ、こんなのってないよ
諦めたらそれまでだ
でも、君なら運命を変えられる
避けようのない滅びも、嘆きも、全て君が覆せばいい
そのための力が、君には備わっているんだから
本当なの?
私なんかでも、本当に何かできるの?こんな結末を変えられるの?
もちろんさ。だから僕と契約して、魔法少女になってよ!
私は巴マミ
あなたたちと同じ、見滝原中の3年生
そして
キュゥべえと契約した、魔法少女よ
はあーはぁ。うん
やあ
はい、これ
うわぁ…。いつも本当にありがとう。さやかはレアなCDを見つける天才だね
あっはは、そんな、運がいいだけだよ。きっと
この人の演奏は本当にすごいんだ。さやかも聴いてみる?
う、い、いいのかな?
本当はスピーカーで聴かせたいんだけど、病院だしね
ええぇー…
あっ
あら、上条君のお見舞い?
(略)

まど☆マギ台詞単語解析

  • 以下ではまど☆マギの平文コーパスを利用する。
文字数抽出
  • 上でスクレイプしたデータをmadmagi.txtとして保存する。
  • nltk.RegexpTokenizerを利用してテキストから正規表現で単語を抽出する。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys 
reload(sys)
sys.setdefaultencoding('utf-8')

import nltk
from nltk.corpus.reader import *
from nltk.corpus.reader.util import *
from nltk.text import Text

jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]')
jp_chartype_tokenizer = nltk.RegexpTokenizer(u'([ぁ-んー]+|[ァ-ンー]+|[\u4e00-\u9FFF]+|[^ぁ-んァ-ンー\u4e00-\u9FFF]+)')
data = PlaintextCorpusReader( './', r'madmagi.txt',
                              encoding='utf-8',
                              para_block_reader=read_line_block,
                              sent_tokenizer=jp_sent_tokenizer,
                              word_tokenizer=jp_chartype_tokenizer )
context =  data.raw()
phrases = nltk.word_tokenize( context )
print '文字数:' + str(len(phrases)) 
  • 実行結果
文字数:3320
文脈を抽出
  • テキスト中のトークンを列挙する。
  • 上のコードに以下を追加する。トークンごとに'/'でデータを区切って表示する。
print 'トークン数:' + str(len(data.words()))
print '/' . join( data.words()[0:len(data.words())] )
  • 結果
    • トークンの区切りが微妙(形態素解析ではない)で統計にはそのまま利用できなさそう。
トークン数:1483
んっん/…/あっ/…!
/あっ/…!
/ひどい/…
/仕方/ないよ/。/彼女一人/では/荷/が/重/すぎた/
/でも/、/彼女/も/覚悟/の/上/だろう/
/そんな/…/あんまりだよ/、/こんなのってないよ/
/諦/めたらそれまでだ/
/でも/、/君/なら/運命/を/変/えられる/
/避/けようのない/滅/びも/、/嘆/きも/、/全/て/君/が/覆/せばいい/
/そのための/力/が/、/君/には/備/わっているんだから/
/本当/なの/?
/私/なんかでも/、/本当/に/何/かできるの/?/こんな/結末/を/変/えられるの/?
/もちろんさ/。/だから/僕/と/契約/して/、/魔法少女/になってよ/!
/私/は/巴/マミ/
/あなたたちと/同/じ/、/見滝原中/の/3/年生/
(略)
解析した単語をまとめて昇順に並べる
  • key(単語)、value(個数)型の辞書を作成する。
  • サンプルコード
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import nltk
from nltk.corpus.reader import *
from nltk.corpus.reader.util import *
from nltk.text import Text

jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]')
jp_chartype_tokenizer = nltk.RegexpTokenizer(u'([ぁ-んー]+|[ァ-ンー]+|[\u4e00-\u9FFF]+|[^ぁ-んァ-ンー\u4e00-\u9FFF]+)')
data = PlaintextCorpusReader( './', r'madmagi.txt',
                              encoding='utf-8',
                              para_block_reader=read_line_block,
                              sent_tokenizer=jp_sent_tokenizer,
                              word_tokenizer=jp_chartype_tokenizer )

node = {}
for i in data.words():
    if node.get(i) is not None:
        node[i] = node[i] + 1
    else:
        node[i] = 1
for k,v in sorted( node.items(), key=lambda x:x[1] ):
    print 'word:'+ k, ' count:' + str(v)
  • 結果
    • トークンの区切りが微妙であるが、「ほむらちゃん」や「死」、「魔法少女」という言葉が特徴的と言える。
word:ほむらちゃん  count:5
word:守  count:5
word:……  count:6
word:う  count:6
word:うん  count:6
word:あ  count:6
word:死  count:6
word:して  count:6
word:だから  count:6
word:な  count:6
word:魔法少女  count:7
word:君  count:7
word:そんな  count:7
word:い  count:7
word:何  count:8
word:…。  count:8
word:え  count:8
word:本当  count:8
word:暁美  count:9
word:!  count:9
word:に  count:11
word:が  count:11
word:鹿目  count:11
word:は  count:11
word:さん  count:12
word:を  count:14
word:の  count:14
word:!  count:16
word:…  count:23
word:?  count:23
word:?  count:26
word:私  count:27
word:…  count:30
word:。  count:49
word:  count:83
word:、  count:141
単語の個数をグラフにplotする
  • matplotlibを利用する。plotした結果を画像として保存する。サンプルコードは次の通り
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import nltk
from nltk.corpus.reader import *
from nltk.corpus.reader.util import *
from nltk.text import Text

import matplotlib.pyplot as plt
from pylab import *
import matplotlib.font_manager as fm

jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]')
jp_chartype_tokenizer = nltk.RegexpTokenizer(u'([ぁ-んー]+|[ァ-ンー]+|[\u4e00-\u9FFF]+|[^ぁ-んァ-ンー\u4e00-\u9FFF]+)')
data = PlaintextCorpusReader( './', r'madmagi.txt',
                              encoding='utf-8',
                              para_block_reader=read_line_block,
                              sent_tokenizer=jp_sent_tokenizer,
                              word_tokenizer=jp_chartype_tokenizer )
fdist = nltk.FreqDist(data.words())
fp = fm.FontProperties(fname='/home/yuta/.fonts/IPAfont00303/ipag.ttf') 
xlabel( u'単語', size='20', fontproperties=fp )
ylabel( u'個数', size='20', fontproperties=fp )
title( u'魔法少女まどか☆マギカの単語数plot', size='20', fontproperties=fp )
fdist.plot()
savefig( 'madmagi_plot.png' )
  • 保存した画像
    • x軸の単語数が潰れてしまっているし、おそらく文字化けしているとも思われる。。


検索
  • テキスト中の単語を検索する。
  • 上のpythonコードに以下を追加する。サンプルでは'魔'という単語を検索する例。
context_p = Text( p.encode( 'utf-8') for p in context )
result = context_p.concordance( '魔' )
print result
  • 結果
か ら 僕 と 契 約 し て 、 魔 法 少 女 に な っ て よ !  
と 契 約 し た 、 魔 法 少 女 よ  
 は あ ー は ぁ  
ち は …   
 彼 女 た ち は 、 魔 法 少 女 。 魔 女 を 狩 る ウ 縺ち は 、 魔 法 少 女 。 魔 女 を 狩 る 者 た ち さ  
 い
た り も す る け れ ど 、 魔 女 を や っ つ け れ ば 、   そ れ で も 、 私 は 魔 法 少 女 だ か ら 。 み ん し か っ た 。 あ な た が 魔 女 に 襲 わ れ た 時 、 間  自 慢 な の   だ か ら 、 魔 法 少 女 に な っ て 、 本  あ 鹿 目 さ ん 、 私 も 魔 法 少 女 に な っ た ん だ  ? ソ ウ ル ジ ェ ム が 魔 女 を 産 む な ら 、 み ん い … ? う ん …    私 、 魔 女 に は な り た く な い ら 、 僕 と 契 約 し て 、 魔 法 少 女 に な っ て よ !

まど☆マギの台詞形態素解析

MeCabを利用して☆マギ台詞の平文コーパス形態素解析する
  • サンプルコード
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import MeCab
mecab = MeCab.Tagger('-Ochasen')
data = open( './madmagi.txt' ).read()
print mecab.parse( data )
  • 結果
ん	ン	ん	名詞-非自立-一般		
っ	ッ	く	動詞-非自立	五段・カ行促音便	連用タ接続
ん	ン	ん	助動詞	不変化型	基本形
…	…	…	記号-一般		
あっ	アッ	あっ	感動詞		
…	…	…	記号-一般		
!	!	!	記号-一般		
あっ	アッ	あっ	感動詞		
…	…	…	記号-一般		
!	!	!	記号-一般		
ひどい	ヒドイ	ひどい	形容詞-自立	形容詞・アウオ段	基本形
…	…	…	記号-一般		
仕方	シカタ	仕方	名詞-ナイ形容詞語幹		
ない	ナイ	ない	助動詞	特殊・ナイ	基本形
よ	ヨ	よ	助詞-終助詞		
。	。	。	記号-句点
  • 上のコードを単語に対する素性を表示するように書き換える。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import MeCab
mecab = MeCab.Tagger('-Ochasen')

data = open( './madmagi.txt' ).read()

node = mecab.parseToNode( data )
phrases = node.next
while phrases:
    print node.surface, node.feature
    node = node.next
  • 結果
ん 名詞,非自立,一般,*,*,*,ん,ン,ン
っ 動詞,非自立,*,*,五段・カ行促音便,連用タ接続,く,ッ,ッ
ん 助動詞,*,*,*,不変化型,基本形,ん,ン,ン
… 記号,一般,*,*,*,*,…,…,…
あっ 感動詞,*,*,*,*,*,あっ,アッ,アッ
… 記号,一般,*,*,*,*,…,…,…
! 記号,一般,*,*,*,*,!,!,!
あっ 感動詞,*,*,*,*,*,あっ,アッ,アッ
… 記号,一般,*,*,*,*,…,…,…
! 記号,一般,*,*,*,*,!,!,!
ひどい 形容詞,自立,*,*,形容詞・アウオ段,基本形,ひどい,ヒドイ,ヒドイ
… 記号,一般,*,*,*,*,…,…,…
仕方 名詞,ナイ形容詞語幹,*,*,*,*,仕方,シカタ,シカタ
MeCabの結果をまとめて昇順に並べる
  • key(単語)、value(個数)型の辞書を作成する。以下はサンプルコード
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import MeCab
mecab = MeCab.Tagger('-Ochasen')

data = open( './madmagi.txt' ).read()

node = mecab.parseToNode( data )
phrases = node.next
dict = {}
while phrases:
    try:
        k = node.surface
        node = node.next
        if dict.get(k) is not None:
            dict[k] = dict[k] + 1
        else:
            dict[k] = 1
    except AttributeError:
       break 

for k,v in sorted( dict.items(), key=lambda x:x[1] ):
    print 'word:'+ k, ' count:' + str(v)
word:さやか  count:6
word:彼女  count:6
word:それ  count:7
word:少女  count:7
word:その  count:7
word:そう  count:7
word:魔法  count:7
word:君  count:8
word:暁美  count:9
word:あっ  count:9
word:あ  count:9
word:こんな  count:10
word:あなた  count:10
word:こと  count:10
word:なっ  count:10
word:そんな  count:10
word:いい  count:11
word:何  count:11
word:鹿目  count:11
word:じゃ  count:12
word:むら  count:13
word:ちゃん  count:13
word:か  count:13
word:う  count:13
word:から  count:13
word:ほ  count:14
word:と  count:14
word:って  count:17
word:え  count:18
word:が  count:18
word:を  count:19
word:し  count:21
word:さん  count:23
word:も  count:23
word:な  count:23
word:で  count:24
word:ん  count:25
word:ね  count:26
word:私  count:28
word:た  count:34
word:ない  count:34
word:に  count:40
word:よ  count:42
word:は  count:42
word:だ  count:43
word:!  count:47
word:て  count:52
ord:だ  count:43
word:!  count:47
word:て  count:52
word:の  count:54
word:。  count:60
word:?  count:62
word:…  count:91
word:、  count:141
JUMANを利用して☆マギ台詞の平文コーパス形態素解析する
  • コード
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys 
reload(sys)
sys.setdefaultencoding('utf-8')

import cJuman 
cJuman.init(['-B', '-e2'])

#JUMANはEUC-JPにしか対応していない
data = open( './madmagi-euc.txt', ).readlines()
print cJuman.parse_opt(data, cJuman.SKIP_NO_RESULT).decode( 'euc-jp' )
  • 出力結果
もちろん もちろん もちろん 副詞 8 * 0 * 0 * 0 "代表表記:もちろん/もちろん"
さ さ さ 助詞 9 終助詞 4 * 0 * 0 NIL
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
だから だから だから 接続詞 10 * 0 * 0 * 0 "代表表記:だから/だから"
、 、 、 特殊 1 読点 2 * 0 * 0 NIL
僕 ぼく 僕 名詞 6 普通名詞 1 * 0 * 0 "代表表記:僕/ぼく 漢字読み:音 カテゴリ:人"
と と と 助詞 9 格助詞 1 * 0 * 0 NIL
契約 けいやく 契約 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:契約/けいやく カテゴリ:抽象物 ドメイン:ビジネス"
して して する 動詞 2 * 0 サ変動詞 16 タ系連用テ形 14 "代表表記:する/する 付属動詞候補(基本) 自他動詞:自:成る/なる"
、 、 、 特殊 1 読点 2 * 0 * 0 NIL
魔法 まほう 魔法 名詞 6 普通名詞 1 * 0 * 0 "代表表記:魔法/まほう カテゴリ:抽象物"
少女 しょうじょ 少女 名詞 6 普通名詞 1 * 0 * 0 "代表表記:少女/しょうじょ カテゴリ:人"
に に に 助詞 9 格助詞 1 * 0 * 0 NIL
なって なって なる 動詞 2 * 0 子音動詞ラ行 10 タ系連用テ形 14 "代表表記:成る/なる 自他動詞:他:成す/なす;他:する/する"
@ なって なって なる 動詞 2 * 0 子音動詞ラ行 10 タ系連用テ形 14 "代表表記:鳴る/なる 自他動詞:他:鳴らす/ならす"
よ よ る 接尾辞 14 動詞性接尾辞 7 母音動詞 1 省略意志形 5 "代表表記:る/る"
@ よ よ る 接尾辞 14 動詞性接尾辞 7 母音動詞 1 文語命令形 18 "代表表記:る/る"
! ! ! 特殊 1 記号 5 * 0 * 0 NIL

まとめ

  • NLTKを利用してまど☆まぎの単語と形態素の解析を行った。NLTKの便利さを少しは実感する事ができた。
  • 元々の台詞の数が少なかったため、「魔法」や「少女」更には登場人物名などの単語が特徴として抽出された。
  • 単語と形態素の頻出度を計算した。matplotlibを利用すると結果をグラフ化して保存できる事も分かった。