繁体   English   中英

python正则表达式否定超前方法

[英]python regex negative lookahead method

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

我首先尝试使用nltk StanfordTagger提取所有标记为组织的单词。 但是,它通常无法回忆起公司的所有名称,并且由于我在每个相关的句子中都使用了标记器,因此花费了很长时间。

因此,我正在尝试提取所有以大写字母开头的单词(或所有字符都由大写字母组成)。

所以我发现下面的正则表达式很有帮助。

(?:[A-Z]+[a-zA-Z\-0-9]*\.?\s?)+

但是,它不能区分段的名称和公司的名称。

例如,

句子:公司的客户包括Conner Peripherals Inc.(以下简称“ Conner”),Maxtor Corporation(以下简称“ Maxtor”)。 Applieds合并净销售额和利润率中最大的份额一直是,并将继续来自Silicon Systems部门向全球半导体行业销售制造设备。

我想提取Conner Peripherals Inc,Conner,Maxtor Corporation,Maxtor,Applieds,但不提取“ Silicon Systems”,因为它是网段的名称。

所以,我尝试使用

(?:[A-Z]+[a-zA-Z\-0-9]*\.?\s?)+(?!segment|Segment)

但是,它仍然提取“ Silicon Systems”。

您能帮我解决这个问题吗?

(或者您对如何仅从文本数据中提取公司名称有任何想法?)

非常感谢!!!

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

>>> 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方法或任何机器学习似乎是一种更好的方法。 我只能解释正则表达式方法的困难和当前问题。

问题在于,期望的匹配项可以包含以空格分隔的短语,并且您要避免匹配以segment结尾的某些短语。 即使您将负前瞻校正为(?!\\s*[Ss]egment) ,并使用\\b[AZ][a-zA-Z0-9-]*(?:\\s+[AZ][a-zA-Z0-9-]*)*\\b\\.?(?!\\s+[sS]egment) ,您仍将匹配Silicon ,这是不需要的匹配的一部分。

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

参见示例正则表达式

\b[A-Z][a-zA-Z0-9-]*(?:\s+[A-Z][a-zA-Z0-9-]*)*\b\.?\s+[sS]egment\b|(\b[A-Z][a-zA-Z0-9-]*(?:\s+[A-Z][a-zA-Z0-9-]*)*\b\.?)

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

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匹配单词边界
  • [AZ][a-zA-Z0-9-]* -大写字母,后跟字母/数字/ -
  • (?:\\s+[AZ][a-zA-Z0-9-]*)* -零个或多个序列
    • \\s+ -1+空格
    • [AZ][a-zA-Z0-9-]* -大写字母,后跟字母/数字/ -
  • \\b尾随单词边界
  • \\.? -可选的.

然后,此块用于构建

  • {0}\\s+[sS]egment\\b我们之前定义的块,后跟
    • \\s+ -1+空格
    • [sS]egment\\b segmentSegment整个单词
  • | - 要么
  • ({0}) -第1组( re.findall实际返回的内容):我们之前定义的块。

filter(None, res) (在Python 2.x中,在Python 3.x中使用list(filter(None, re.findall(rx, s))) )会过滤掉最终列表中的空项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM