MeCabを使った575判定

前の記事で、形態素解析器を使って、日本語から読みを取得できるようになりました。この記事では、その読みが575かどうかを判定できるようにコードを書きます。

Q. 575判定はどうすればいい? A. 音を数えて、文節の区切れと575が一致するかを見よう

前回のプログラムを変更します。

  • なんとなく平仮名にしたかった
  • 形態素では区切れていても助詞や助動詞で始まる五音や七音を除きたかった
  • 文字数ではなく音(モーラ)で数えたい(「きゃ」は1音だとする)

などを追加実装したものが以下のプログラムです。

import jaconv
import MeCab
import regex

def extract_hiragana(text):
    return "".join(regex.findall(r'[\p{Hiragana}ー]', text))

m = MeCab.Tagger() #形態素解析用objectの宣言

def get_pronunciation_list(text):
    m_result = m.parse(text).splitlines()[:-1] #mecabの解析結果の取得
    pro = [] #いい感じに切った読み全体を格納する変数
    for v in m_result:
        if '\t' not in v: continue
        surface = v.split('\t')[0] #表層形
        p = v.split('\t')[1] #読みを取得
        if p == '*':#発音が取得できていないときは諦める
            continue
        if v.split('\t')[4].startswith("助詞") or v.split('\t')[4].startswith("助動詞") and pro:
            pro[-1] += p
        else:
            pro.append(p)
    pro = [jaconv.kata2hira(p) for p in pro] #ひらがなに変換
    pro = [extract_hiragana(p) for p in pro if p] #余計な記号を削除
    return pro

def is_575(text: str) -> bool:
    words = get_pronunciation_list(text)
    length = 0
    reversed_expected_length_list = [5, 7, 5]
    for word in words:
        if not reversed_expected_length_list:  # 575が終わったのにまだ続く
            return False
        length += len(regex.sub(r'[ぁぃぅぇぉゃゅょ]', '', word))  # 1音を構成しない文字
        if length == reversed_expected_length_list[-1]:
            length = 0
            reversed_expected_length_list.pop()
    if reversed_expected_length_list:  # 575と切り取れなかった
        return False
    return True

text = '古池や蛙飛びこむ水の音'
print(is_575(text))

なお、今回は字余りを許してません。あくまで575の判定にしています。ここは好みがあると思うので、いろんな文章を入れてみて、自分好みの575判定条件を作りましょう。

ちなみに上記のプログラムは「五月雨をあつめて早し最上川 」を「さいじょーがわ」と読んでしまうなど、完璧ではありません。形態素解析の改善は他の辞書を使うとかsudachiなど他の形態素解析器を使うなどの手法はありますが、精度の向上は難しいため、今回はMeCabを信じて進みます。

is_575関数は文字列の読みが五・七・五かを判定してくれます。今回はほとんど形態素解析器MeCabがやってくれて、MeCabを正しく使えば良いだけで済みました。

能力2 「各メッセージが五・七・五かを判定する」を獲得しました。

次の記事から、能力3「Slackにメッセージを送信する」を獲得します。

© 2019- estie, inc.