【问题标题】:Find rhyme using NLTK in Python在 Python 中使用 NLTK 找韵
【发布时间】:2014-09-07 20:36:04
【问题描述】:

我有一首诗,我希望 Python 代码只打印那些彼此押韵的单词。

到目前为止,我能够:

  1. wordpunct_tokenize()破诗句
  2. 通过删除标点符号来清理单词
  3. 将诗中每个句子的最后一个单词存储在一个列表中
  4. 使用cmudict.entries() 生成另一个列表,其中元素作为最后的单词及其发音。

我坚持下一步。我应该如何尝试匹配这些发音?总之,我的主要任务是找出两个给定的单词是否押韵。如果押韵,则返回True,否则返回False

【问题讨论】:

  • 那么您的问题是如何使用 nltk 查找 2 个单词是否押韵?
  • 是的。单词可能出现在一串文本中
  • 我认为这个问题一点意义都没有。韵的程序识别可能有很多潜在的研究应用......

标签: python nltk


【解决方案1】:

Pronouncing library 在这方面做得很好。无需破解,加载速度快,并且基于 CMU 发音词典,因此非常可靠。

https://pypi.python.org/pypi/pronouncing

来自他们的documentation

>>> import pronouncing
>>> pronouncing.rhymes("climbing")
['diming', 'liming', 'priming', 'rhyming', 'timing']

【讨论】:

    【解决方案2】:

    Here我找到了一种使用 NLTK 为给定单词查找押韵的方法:

    def rhyme(inp, level):
         entries = nltk.corpus.cmudict.entries()
         syllables = [(word, syl) for word, syl in entries if word == inp]
         rhymes = []
         for (word, syllable) in syllables:
                 rhymes += [word for word, pron in entries if pron[-level:] == syllable[-level:]]
         return set(rhymes)
    

    其中inp 是一个单词,level 表示押韵应该有多

    所以你可以使用这个函数来检查两个单词是否押韵,你可以只检查一个是否在其他允许的押韵中:

    def doTheyRhyme(word1, word2):
        # first, we don't want to report 'glue' and 'unglue' as rhyming words
        # those kind of rhymes are LAME
        if word1.find(word2) == len(word1) - len(word2):
            return False
        if word2.find(word1) == len(word2) - len(word1): 
            return False
    
        return word1 in rhyme(word2, 1)
    

    【讨论】:

    • 它适用于完美的押韵!但我没有得到 level 参数。我尝试了一些不完美的押韵,例如"laid" 和 "lay" 以及 'level' 的大数字,但它不返回 True。
    【解决方案3】:

    使用 soundex 或双变音来确定它们是否押韵。 NLTK 似乎没有实现这些,但快速的 Google 搜索显示了一些实现。

    【讨论】:

    • 这么热,帽子韵吗?因为这是使用变音位时非常常见的误报。我不认为这些库用于查找押韵的单词。
    【解决方案4】:

    聚会有点晚了,但我正在做一个项目,以找到许多押韵线进行处理。我从这个问题线程开始,并被kender 接受的答案引发。很高兴知道,在识别成千上万的韵律时,您可以利用字典查找来大大提高速度。

    这也针对 python 3.x 进行了更新。

    将 CMU 发音字典存储为 json 文件,其中包含一个 init 函数和一个将条目从元组转换为字典的函数。

    # global
    json_entries = None
    
    def tup2dict(tup, di):
    for a, b in tup:
        di.setdefault(a, []).append(b)
    return di
    
    def init_cmu(args):
        import nltk
        nltk.download('cmudict')
        nltk.corpus.cmudict.ensure_loaded()
        cmu_entries = nltk.corpus.cmudict.entries()
        cmu_dict = dict()
        tup2dict(cmu_entries, cmu_dict)
        with open('./maps/cmu.json', 'w') as convert_file:
            convert_file.write(json.dumps(cmu_dict))
    

    如果您在脚本中使用了需要确定韵律的函数,则可以在其顶部调用此函数以确保您可以访问字典。

    def require_rhyme_dict():
        global json_entries
        if json_entries:
            return
        try:
            jsonf = open('./maps/cmu.json', 'r')
        except:
            pass
        else:
            # Global
            json_entries = dict(json.load(jsonf))
            jsonf.close()
            print('json_entries loaded.')
    

    最后,这是kender 的押韵功能的修改版本,它使用字典和不同的子词检查方法(我遇到了一些极端情况,押韵不是“跛脚”,但单词是'不允许根据词首索引和长度押韵。具体例子记不清了,很少见)。

    当连续调用数千次时,下面的函数调用比一旦找到一个单词就遍历所有nltk cmu条目以查找发音音节列表要快得多。与以前一样,级别是指单词之间的多少发音音节,匹配在末尾找到的那些,应该匹配以构成押韵。在本例中,如果有多个发音,也会检查每个单词的发音。

    def isContainSameWord(word1, word2):
        if word1 in word2 or word2 in word1:
            return True
        else:
            return False
    
    def isRhyme(word1, word2, level):
        require_rhyme_dict()
        global json_entries
        if isContainSameWord(word1, word2):
            return False
        word1_syllable_arrs = json_entries.get(word1)
        word2_syllables_arrs = json_entries.get(word2)
        if not word1_syllable_arrs or not word2_syllables_arrs:
            return False
        for a in word1_syllable_arrs:
            for b in word2_syllables_arrs:
                if a[-level:] == b[-level:]:
                    return True
        return False
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-25
      • 1970-01-01
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-03
      • 2015-03-12
      相关资源
      最近更新 更多