後述するサイトの情報を参考にしたら、割とすんなり動きました。 ただ、やや動作に難があったり、エンコード沼にはまりそうになったりして、工夫してコードを書かないといけなかったので、大変でした。
MeCab.Tagger.parseToNode(str) が正常に動作しない
str(res.surface.encode())
と書かないと単語が取得できなかったり、res.surface
が取得できなかったりと、動作が不安定です。
結局、MeCab.Tagger.parse(str)
を行ごとにforで回してデータを取得するようにしました。
コード
# coding=utf-8 def is575(text, amari=False, tarazu=False, partial=False): import MeCab import re mt = MeCab.Tagger() res = mt.parse(text) lensum = [0] pat = re.compile(r'[ゃゅょャュョ]') for s in res.splitlines(): if s == 'EOS': continue surface, feature = s.split("\t") features = feature.split(",") if features[0] != '記号': if len(features) >= 8: lensum.append(lensum[-1] + len(pat.sub('', features[7]))) else: lensum.append(lensum[-1] + len(pat.sub('', surface))) senryu = 5, 7, 5 offset = 0 start = 0 end = 1 while start < len(lensum) and offset < 3: if(any([ lensum[end] - lensum[start] == senryu[offset], tarazu and lensum[end] - lensum[start] == senryu[offset]-1, amari and lensum[end] - lensum[start] == senryu[offset]+1])): offset += 1 start = end end = start + 1 if partial and offset == 3: return True else: end += 1 if end == len(lensum): if partial: offset = 0 start += 1 end = start + 1 else: break return offset == 3 if __name__ == '__main__': assert is575('五月雨を集めて早し最上川') assert is575('うむ、五月雨を集めて早し最上川とはよく言ったものですよ', partial=True)
引数に、amari=True
tarazu=True
を渡すと、それぞれ字余り・字足らずを許容するようになります。
応用すれば57577や7775も判定できるし、文章内に575があるかどうかの判定だってできるようになります。
きっかけ
575って楽しくない?