MeCab-Pythonで分かち書きと形態素解析

MeCabでwakatiとchasenを使うと、それぞれ分かち書き形態素解析ができる。 これらの結果を利用しやすくするために、前者は単語のリスト、後者は単語と品詞のセットのリストとして取得できるようにした。

分かち書き

まずはMeCabの使い方から。最初は分かち書き。 パラメーターに"-Owakati"を指定する。

text = '日本語の自然言語処理は本当にしんどい。'
tagger = MeCab.Tagger("-Owakati")        
result = tagger.parse(text)
print result

結果。これをリストにする。

日本語 の 自然 言語 処理 は 本当に しんどい 。

分かち書き結果をリストで取得

メソッドは以下の通り。 文字コードとか、不要な情報とかを除去してリスト化している。

def word_tokenize(self, doc):
    """
    Execute wakati.
    """
    # Convert string type in case of unicode type
    doc_ex = doc
    if type(doc) is types.UnicodeType:
        doc_ex = doc.encode("utf-8")

    # Execute wakati
    tagger = MeCab.Tagger("-Owakati")        
    result = tagger.parse(doc_ex)

    # Make word list
    ws = re.compile(" ")
    words = [word.decode("utf-8") for word in ws.split(result)]
    if words[-1] == u"\n":
        words = words[:-1]

    return words

結果は次の通り。 NLTKJPは今回作った2つのメソッドのクラス名。 nltkjp.word_tokenize()は、nltk.tokenize.word_tokenize()の日本語版のつもり。

>>> text = '日本語の自然言語処理は本当にしんどい。'
>>> from nltkjp import NLTKJP
>>> nltkjp = NLTKJP()
>>> result = nltkjp.word_tokenize(text)
>>> print result
[u'\u65e5\u672c\u8a9e', u'\u306e', u'\u81ea\u7136', u'\u8a00\u8a9e', u'\u51e6\u7406', u'\u306f', u'\u672c\u5f53\u306b', u'\u3057\u3093\u3069\u3044', u'\u3002']
>>>
>>> for r in result:
>>>     print r,
日本語 の 自然 言語 処理 は 本当に しんどい 。

形態素解析

次に形態素解析。 パラメーターに"-Ochasen"を指定。

tagger = MeCab.Tagger('-Ochasen')
result = tagger.parseToNode(text)
while result:
    print '%-10s \t %-s' % (result.surface, result.feature)
    result = result.next

surfaceで単語、featureで解析結果が得られる。 解析結果のうち、今回は品詞だけ必要になる。

              BOS/EOS,*,*,*,*,*,*,*,*
日本語    名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
の          助詞,連体化,*,*,*,*,の,ノ,ノ
自然       名詞,形容動詞語幹,*,*,*,*,自然,シゼン,シゼン
言語       名詞,一般,*,*,*,*,言語,ゲンゴ,ゲンゴ
処理       名詞,サ変接続,*,*,*,*,処理,ショリ,ショリ
は          助詞,係助詞,*,*,*,*,は,ハ,ワ
本当に    副詞,一般,*,*,*,*,本当に,ホントウニ,ホントーニ
しんどい     形容詞,自立,*,*,形容詞・アウオ段,基本形,しんどい,シンドイ,シンドイ
。          記号,句点,*,*,*,*,。,。,。
             BOS/EOS,*,*,*,*,*,*,*,*

分かち書き結果を単語と品詞のセットのリストで取得

メソッドは以下の通り。 解析結果をカンマ(,)でsplitして最初だけ取得。 あと、解析結果の最初と最後がいらないので除去。

def word_and_class(self, doc):
    """
    Get word and class tuples list.
    """
    # Convert string type in case of unicode type
    doc_ex = doc
    if type(doc) is types.UnicodeType:
        doc_ex = doc.encode("utf-8")

    # Execute class analysis
    tagger = MeCab.Tagger('-Ochasen')
    result = tagger.parseToNode(doc_ex)

    # Extract word and class
    word_class = []
    while result:
        word = result.surface.decode("utf-8", "ignore")
        clazz = result.feature.split(',')[0].decode('utf-8', 'ignore')
        if clazz != u'BOS/EOS':
            word_class.append((word, clazz))
        result = result.next

        return word_class

結果は次の通り。

>>> result = nltkjp.word_and_class(text)
>>> for r in result:
>>>     print '%-10s \t %-s' % (r[0], r[1])
日本語            名詞
の              助詞
自然           名詞
言語           名詞
処理           名詞
は              助詞
本当に            副詞
しんどい         形容詞
。              記号