janomeライクなmecabのラッパー作った話


概要

mecabの爆速形態要素解析とNEologdの最新辞書をjanomeのイケてるインターフェイスで使いたい人のためのライブラリをつくりました.

きっかけ

janomeのAnalyzerがイケてますよね.てか基本的にjanomeがインストールもしやすいし使いやすいんですよね.でもNEologdの辞書を使うのはvery experimentalって謳ってるのでなんだかなぁと思っていました.じゃあ形態要素解析の部分はmecabとNEologdに任せて,それを使いやすくするためのラッパーを作ろうと思ったのがきっかけです.

その名もwakame!

githubはこちら
PyPIはこちら
janomeの「me」の部分とめかぶの派生からのwakameです.作者がわかめ好きだからではありません.
最初はmecab-no-meという名前で作ってたけど先輩から「wakameでよくね?」って言われて採用させてもらいました.よくわからない名前になる危機を救ってくれた先輩に感謝.

インストール

wakame自体はpipで簡単にインストールできます.

pip install wakame

ただ,mecabを使うのでmecabのインストールが別途必要になります.READMEにもいちおう記載していますので,そちらを参照してください.

使い方

基本的にはjanomeのように使えることを目指して使っています.

基本的な使い方

READMEに載っているものと同じですが,基本的な使い方は以下のとおりです.

from wakame.tokenizer import Tokenizer
from wakame.analyzer import Analyzer
from wakame.charfilter import *
from wakame.tokenfilter import *

text = '和布ちゃんこんにちは'

# 基本的な使い方
tokenizer = Tokenizer()
tokens = tokenizer.tokenize(text)
for token in tokens:
    print(token)
# >> 和布 名詞,一般,*,*,*,*,和布,ワカメ,ワカメ
# >> ちゃん  名詞,接尾,人名,*,*,*,ちゃん,チャン,チャン
# >> こんにちは    感動詞,*,*,*,*,*,こんにちは,コンニチハ,コンニチワ

# 分かち書き
tokens = tokenizer.tokenize(text, wakati=True)
print(tokens)
# >> ['和布', 'ちゃん', 'こんにちは']

# 辞書をNEologdにする場合
tokenizer = Tokenizer(use_neologd=True)
tokens = tokenizer.tokenize(text)
for token in tokens:
    print(token)
# >> 和布 名詞,一般,*,*,*,*,和布,ワカメ,ワカメ
# >> ちゃん  名詞,接尾,人名,*,*,*,ちゃん,チャン,チャン
# >> こんにちは    感動詞,*,*,*,*,*,こんにちは,コンニチハ,コンニチワ


# filterを利用する場合
# '和布'を'wakame'に変える
char_filters = [RegexReplaceCharFilter('和布', 'wakame')]
# '名詞'のみ取り出すが,'名詞,接尾'のものは取り出さないようにする.
token_filters = [POSKeepFilter('名詞'), POSStopFilter(['名詞,接尾'])]
analyzer = Analyzer(tokenizer, char_filters=char_filters, token_filters=token_filters)
tokens = analyzer.analyze(text)
for token in tokens:
    print(token)
# >> wakame 名詞,固有名詞,組織,*,*,*,*

pandas.DataFrameで扱う

データを見たり,自分でゴニョゴニョするときにDataFrame型式のほうが使いやすい場面があるなぁと思い,surfaceやらpart_of_speechやらをDataFrameで返せるメソッドを用意しました.

# tokenの情報をDataFrameで用いる場合
tokenizer = Tokenizer()
analyzer = Analyzer(tokenizer)
df = analyzer.analyze_with_dataframe(text)
print(df)
# >>   surface part_of_speech infl_type infl_form base_form reading phonetic
# >> 0      和布      名詞,一般,*,*         *         *        和布     ワカメ      ワカメ
# >> 1     ちゃん     名詞,接尾,人名,*         *         *       ちゃん     チャン      チャン
# >> 2   こんにちは      感動詞,*,*,*         *         *     こんにちは   コンニチハ    コンニチワ

独自のfilter

  • urlを特定の文字列に変換する URLReplaceFilter
  • 特定の品詞を特定の文字列に置き換える POSReplaceFilter
  • 変換された文字列をもとに戻す RestoreFilter

なんでもとに戻すfilterを作ったかというと,「くんさんにしたいけどちゃんはそのまま使いたい」みたいなときがあったからです.

text = '鰹くんと栄螺さんは和布ちゃんの兄妹です'
tokenizer = Tokenizer()
token_filters = [POSReplaceFilter(['名詞,接尾'], '様'), RestoreFilter(['ちゃん'])]
analyzer = Analyzer(tokenizer, token_filters=token_filters)
text = ''.join(analyzer.analyze_with_dataframe(text)['surface'])
print(text)
# >> 鰹様と栄螺様は和布ちゃんの兄妹です

このように「あったら便利だなぁ」って機能を追加しております.
大きな文書を品詞分解するのもmecabを使ってるので結構速く処理できます.

今後

今後もほしいfilterがあったらぼちぼち追加していこうと思います.
暖かく見守ってくれたらうれしいです.