首页 > 解决方案 > 如何在 nltk 语法中直接使用单词

问题描述

我正在尝试使用 python NLTK 从给定的德国地址中提取公司名称。这是我使用的代码,

import nltk

address="CompanyName GmbH * Keltenstr. 16 * 123456 Kippenheim * Deutschland"
tokens = nltk.word_tokenize(address)
textTokens = nltk.Text(tokens)
POStagList = nltk.pos_tag(textTokens)
print(POStagList)

grammar = """
        NP: 
            {<NN.?|JJ|FW>GmbH}"""


cp = nltk.RegexpParser(grammar)
result = cp.parse(POStagList)

for subtree in result.subtrees(filter=lambda t: t.label() == 'NP'):
   print("NP Subtree:", subtree)

我需要输出:CompanyName GmbH

有时,它可能不是GmbH ,而是corpInc.llc

如何解决这个问题?

如何在语法中直接使用字符串值和转义序列字符?

标签: regexpython-3.xnltk

解决方案


除了将语法与文字字符串混合之外,您还可以使用正则表达式来解决:用 POS 标记标记,然后只在已知单词(如GmbH)之前获取您需要的标记。

代码看起来像

import nltk
import re
address="CompanyName GmbH * Keltenstr. 16 * 123456 Kippenheim * Deutschland"
tokens = nltk.word_tokenize(address)
textTokens = nltk.Text(tokens)
POStagList = nltk.pos_tag(textTokens)
joined = ' '.join(["{}<{}>".format(word,tag) for word,tag in POStagList])
grammar = r'NN[^>]?|JJ|FW' # regex! 
print([re.sub("<(?:{})>".format(grammar), "", x.strip()) for x in re.findall(r'((?:\S+<(?:{0})> )+)(?:GmbH|Inc|corp|llc)<(?:{0})>'.format(grammar), joined)])

输出:['CompanyName']

在这里,语法是使用正则表达式指定的,例如NN[^>]?|JJ|FWwhere[^>]?匹配任何 char but >(只是为了确保我们不匹配>,就像.会那样)。之后,((?:\S+<(?:NN[^>]?|JJ|FW)> )+)(?:GmbH|Inc|corp|llc)<(?:NN[^>]?|JJ|FW)>正则表达式将找到您需要的所有匹配项,但由于它们包含标签,因此必须使用re.sub仅使用<(?:NN[^>]?|JJ|FW)>正则表达式的 a 来删除它们。

主要的正则表达式细节:

  • ((?:\S+<(?:NN[^>]?|JJ|FW)> )+)- 第 1 组:一个或多个 1+ 非空白字符序列,后跟<,然后NN+ 任何 1 或 0 个除>, 或JJ或以外的字符FW>然后是空格
  • (?:GmbH|Inc|corp|llc)- 任何备选方案:GmbHInccorpllc
  • <(?:NN[^>]?|JJ|FW)>- <, + 除, or或之外的NN任何 1 或 0 个字符。>JJFW

推荐阅读