前の記事で、形態素解析器を使って、日本語から読みを取得できるようになりました。この記事では、その読みが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にメッセージを送信する」を獲得します。