私が歌川です

@utgwkk が書いている

Python3.4.3でMeCabの導入に成功したので、入力文字列が575かどうか判定するスクリプトを書いた

後述するサイトの情報を参考にしたら、割とすんなり動きました。 ただ、やや動作に難があったり、エンコード沼にはまりそうになったりして、工夫してコードを書かないといけなかったので、大変でした。

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って楽しくない?

参考