python正则表达式负前瞻方法

python正则表达式负前瞻方法,python,regex,Python,Regex,我现在从文本数据(10-k报表数据)中提取公司名称 我首先尝试使用nltk StanfordTagger并提取所有标记为organization的单词。然而,它常常无法回忆起所有公司的名字,而当我将tagger应用于每一个相关的句子时,花了很长时间 所以,我试图提取所有以大写字母开头的单词(或者单词字符都由大写字母组成) 所以我发现下面的正则表达式很有用 (?:[A-Z]+[a-zA-Z\-0-9]*\.?\s?)+ 然而,它无法区分分部名称和公司名称 比如说, 句子: 该公司的客户包括康纳外

我现在从文本数据(10-k报表数据)中提取公司名称

我首先尝试使用nltk StanfordTagger并提取所有标记为organization的单词。然而,它常常无法回忆起所有公司的名字,而当我将tagger应用于每一个相关的句子时,花了很长时间

所以,我试图提取所有以大写字母开头的单词(或者单词字符都由大写字母组成)

所以我发现下面的正则表达式很有用

(?:[A-Z]+[a-zA-Z\-0-9]*\.?\s?)+
然而,它无法区分分部名称和公司名称

比如说,

句子: 该公司的客户包括康纳外围设备有限公司(“康纳”), Maxtor公司(“Maxtor”)。Applieds合并净销售额和盈利能力的最大比例一直并将继续来自硅系统部门的制造设备对全球半导体行业的销售

我想提取Conner外围设备公司、Conner、Maxtor Corporation、Maxtor、Applieds,但不提取“Silicon Systems”,因为它是细分市场的名称

所以,我试着使用

(?:[A-Z]+[a-zA-Z\-0-9]*\.?\s?)+(?!segment|Segment)
然而,它仍然提取“硅系统”

你能帮我解决这个问题吗

(或者你知道如何从文本数据中只提取公司名称吗?)


非常感谢

您需要捕获所有连续文本!然后,将以大写开头的单个单词标记为非捕获(
?:
),以便捕获连续单词

>>> re.findall("((?:[A-Z]+[a-zA-Z\-0-9']*\.?\s?)+)+?(?![Ss]egment)",sentence)
["The Company's ", 'Conner Peripherals Inc.', 'Conner', 'Maxtor Corporation ', 'Maxtor', 'The ', 'Applieds ', '']

NLTK方法,或任何机器学习,似乎是一种更好的方法。我只能解释正则表达式方法的困难和当前问题

问题是,预期的匹配可能包含空格分隔的短语,并且您希望避免匹配以
结尾的特定短语。即使您将负前瞻修正为
(?!\s*[Ss]egment)
,并使用类似的方式使模式线性化,您仍将匹配
,这是不需要的匹配的一部分

您可能会尝试匹配所有这些实体,并在匹配后丢弃,通过将它们捕获到组1中,仅将这些实体保留在其他上下文中

见:

由于它很笨拙,您应该考虑从块动态地构建它:

import re
entity_rx = r"\b[A-Z][a-zA-Z0-9-]*(?:\s+[A-Z][a-zA-Z0-9-]*)*\b\.?"
rx = r"{0}\s+[sS]egment\b|({0})".format(entity_rx)
s = "The Company's customers include, among others, Conner Peripherals Inc.(\"Conner\"), Maxtor Corporation (\"Maxtor\"). The largest proportion of Applieds consolidated net sales and profitability has been and continues to be derived from sales of manufacturing equipment in the Silicon Systems segment to the global semiconductor industry."
matches = filter(None, re.findall(rx, s))
print(matches) 
# => ['The Company', 'Conner Peripherals Inc.', 'Conner', 'Maxtor Corporation', 'Maxtor', 'The', 'Applieds']
所以

  • \b
    -匹配单词边界
  • [A-Z][A-zA-Z0-9-]*
    -大写字母后跟字母/数字/
    -
  • (?:\s+[A-Z][A-zA-Z0-9-]*)*
    -零个或多个
    • \s+
      -1+空格
    • [A-Z][A-zA-Z0-9-]*
      -大写字母后跟字母/数字/
      -
  • \b
    -尾随词边界
  • \?
    -可选的
然后,该块用于构建

  • {0}\s+[sS]egment\b
    之前定义的块
    • \s+
      -1+空格
    • [sS]egment\b
      -要么
      要么
      整字
  • |
    -或
  • ({0})
    -组1(实际上返回的是
    re.findall
    ):我们之前定义的块

filter(None,res)
(在Python2.x中,在Python3.x中使用
list(filter(None,re.findall(rx,s))
)将过滤掉最终列表中的空项。

如果我在文本上使用带有
re.findall
的第一个正则表达式,我会得到
['Company','Inc','Conner','Corporation','Maxtor','the','Applieds','Systems']
。这与您在问题中所说的不匹配,但您也说过正则表达式工作得很好。我遗漏了什么吗?@SethMMorton噢,我想你在寻找regex result的子组(这是re.findall的基本设置)。我正在使用re.finditer方法,只捕获完整匹配!包含所需的所有相关信息非常重要,这样人们就可以复制您的结果并帮助您。此外,如果您不想捕获该组,那么您应该将其设置为非捕获,以便清楚地知道您不会捕获该组。正则表达式很难按原样阅读,最好尽可能添加自文档。@SethMMorton对不起,我认为这只是一个微不足道的细节!我会编辑这个问题!我的问题似乎不够明显。我试过你的正则表达式,但它仍然捕获“硅系统”。请在python解释器中尝试!它只捕获['The','Applieds',']
import re
entity_rx = r"\b[A-Z][a-zA-Z0-9-]*(?:\s+[A-Z][a-zA-Z0-9-]*)*\b\.?"
rx = r"{0}\s+[sS]egment\b|({0})".format(entity_rx)
s = "The Company's customers include, among others, Conner Peripherals Inc.(\"Conner\"), Maxtor Corporation (\"Maxtor\"). The largest proportion of Applieds consolidated net sales and profitability has been and continues to be derived from sales of manufacturing equipment in the Silicon Systems segment to the global semiconductor industry."
matches = filter(None, re.findall(rx, s))
print(matches) 
# => ['The Company', 'Conner Peripherals Inc.', 'Conner', 'Maxtor Corporation', 'Maxtor', 'The', 'Applieds']