Python 2.X:正则表达式查找以“.inc”结尾的所有公司名称

时间:2017-11-15 19:54:53

标签: python regex

我正试图从新闻稿中提取公司名称。例如,下面有一个新闻稿的片段(法语),其中包含以.inc结尾的七家公司的列表。

  

En effet,RevenuQuébecavait des motifs raisonnables de croire que ces entreprisesavaientutilisédefausses factures provenant deplusieurssociétés,dont Asphalte Vrac Transport inc。 9163-6704 Québecinc。 EntrepriseDenisDupréinc。 Gestion Jean M. Machado inc。 Impact Technologie Environnementale inc。,< strong> Les entreprisesLucClémentinc。 et Transport Vrac Globe International inc。

我正在尝试使用以下代码提取所有名称:

aa = re.findall('inc\.,? (.*?inc\.)', text)

我设法捕获了不少,但由于某种原因我无法想象,我无法全部提取它们。这似乎是微不足道的,但它已经让我踩了几个小时....

感谢任何帮助!

5 个答案:

答案 0 :(得分:5)

使用regex模块(而非re),您可以使用此解决方案。

代码

选项1

这是原始正则表达式,仅匹配inc.。这也不允许包含et的公司名称。有关更全面的正则表达式,请参阅选项2

See regex in use here

[\p{Lu}\p{N}](?:(?!et)[^,])*inc\.

选项2

对于更全面的正则表达式,还会检查其他公司实体,例如ltd.sons,您可以使用以下正则表达式。

See regex in use here

(?:et|,)[^,]*?([\p{Lu}\p{N}][^,]*?\s(?:inc\.|sons|ltd\.))

注意:在某些版本的正则表达式中,您可以使用\K令牌。此标记重置报告的匹配的起始点(任何以前消耗的字符不再包含在最终匹配中)。如果您的正则表达式引擎支持\K令牌(并且不将其转换为文字K),则可以使用以下内容(实际上无需捕获组)。

See regex in use here

(?:et|,)[^,]*?\K[\p{Lu}\p{N}][^,]*?\s(?:inc\.|sons|ltd\.)
              ^^

结果

输入

  

En effet,RevenuQuébecavaitdes motifs raisonnables de croire que   ces entreprisesavaientutilisédefausses factures provenant de   plusieurssociétés,dont Asphalte Vrac Transport inc。,9163-6704   Québecinc。,EntrepriseDenisDupréinc。,Gestion Jean M. Machado   inc。,Impact Technologie Environnementale inc。,Les entreprises Luc   克莱门特公司et Transport Vrac Globe International inc。

输出

Asphalte Vrac Transport inc.
9163-6704 Québec inc.
Entreprise Denis Dupré inc.
Gestion Jean M. Machado inc.
Impact Technologie Environnementale inc.
Les entreprises Luc Clément inc.
Transport Vrac Globe International inc.

说明

选项1

  • [\p{Lu}\p{N}]匹配集合中的任何内容(在本例中为\p{Lu} - 任何语言中的任何大写字符(包括用于大写法语字符的Unicode和用于数字公司的数字)
  • (?:(?!et)[^,])*符合以下任意次数(tempered greedy token
    • (?!et)否定前瞻确保后续内容与et字面上不匹配
    • [^,]匹配除逗号,之外的任何字符
  • inc\.按字面意思匹配inc.

选项2

  • (?:et|,)字面匹配et或逗号,
  • [^,]*?匹配集合中不存在的任何字符(除逗号,之外的任何字符,但会尽可能少
  • ([\p{Lu}\p{N}][^,]*?\s(?:inc\.|sons|ltd\.))将以下内容捕获到捕获组1中
    • [\p{Lu}\p{N}]匹配任何Unicode大写字符或Unicode编号(对于数字公司)
    • [^,]*?匹配集合中不存在的任何字符(除逗号,之外的任何字符,但会尽可能少
    • \s匹配空白字符
    • (?:inc\.|sons|ltd\.)匹配以下任一项
      • inc\.按字面意思匹配inc.
      • sons按字面意思匹配sons
      • ltd\.按字面意思匹配ltd.

备注

正则表达式模块与重新

使用regex模块允许我们使用Unicode字符类,例如\p{Lu},以确保我们也能够发现公司名称以大写Unicode字符开头的可能性,例如É

捕捉特殊案例

正则表达式链接(在代码下)包含一个要测试的附加字符串:

, Étoile Simpsons et sons, Étoile Simpsons inc., Étoile et Simpsons inc.

添加此附加行后,只应捕获以下字符串(根据OP的规范,有效的公司名称):

  • Étoile Simpsons et sons
  • Étoile Simpsons inc.
  • Étoile et Simpsons ltd.

这提出了一些挑战,包括:

  • 公司名称以大写Unicode字符É开头。
    • 这意味着我们必须确保Unicode大写字母兼容性,因此使用类似[A-Z]的内容无法确保名称以大写字母开头。
  • 公司以sons结尾,但也包含sonssons的首次匹配时无法停止)。
    • Étoile Simpsons et sons为例。
      • 这不应该在sons的{​​{1}}结束。天生的本能(至少在正则表达式中)可能是使用Simpsons来断言单词边界。尽管这可能是首选方法,但在这种情况下它不起作用。以法语单词\b为例。使用blésons实际上会在\b中匹配,因为即使启用了blésons标记,正则表达式引擎也很少与Unicode字符匹配\b(这就是我使用u的原因代替)。
  • 公司名称结束后出现\s字样(在句子sons中)。它不得超越公司名称的结尾。
    • 这是使用延迟量词的一个很好的例子,即Their sons et sons, les sons.。让它变得懒惰将允许它在第一场比赛时停止而不是匹配整个句子错误
  • 字符串.*?包含有效公司名称的所有部分(以大写字母开头的单词,后跟单词Their sons et sons, les sons.),但这不应该匹配,因为它不是公司名称。
    • 由于OP在每个公司名称之前指定了sons,我使用它来确定什么是公司名称。

答案 1 :(得分:1)

这种模式似乎可以解决问题:

   >>> string = """En effet, Revenu Québec avait des motifs raisonnables de croire que ces entreprises avaient utilisé de fausses factures provenant de plusieurs sociétés, dont Asphalte Vrac Transport inc., 9163-6704 Québec inc., Entreprise Denis Dupré inc., Gestion Jean M. Machado inc., Impact Technologie Environnementale inc., Les entreprises Luc Clément inc. et Transport Vrac Globe International inc."""
   >>> pattern = r'((?:[A-Z0-9\-]\.?\w*\s?(?:[a-z0-9\-]\w*\s?)?)+ inc\.)'
   >>> m = re.findall(pattern, string)
   >>> print('\n'.join(m))

   Asphalte Vrac Transport inc.
   9163-6704 Québec inc.
   Entreprise Denis Dupré inc.
   Gestion Jean M. Machado inc.
   Impact Technologie Environnementale inc.
   Les entreprises Luc Clément inc.
   Transport Vrac Globe International inc.

<强>解释

   [A-Z0-9\-] # match an uppercase letter or number or dash
   \.?        # match optional dot
   \w*        # match alpha-numeric chars 0 or more times
   \s?        # match optional white-space

   (?:[a-z0-9\-]\w*\s?)? # same again except with lowercase letters
                         # the ? means 0 or 1 times

    inc\.     # match ' inc.'
   (?: ... )  # non-capturing group
   ( ... )    # capturing group (whole thing)
   x?          # match x optional
   x*          # in this case match x 0 or more times
   x+          # match x 1 or more times

答案 2 :(得分:0)

在这种情况下,您可以避免使用regex,而是尝试:

text.split(“,”)

然后遍历创建的list并查找".inc"

答案 3 :(得分:0)

aa = [s.strip() for s in text.split(',') if s.lower().endswith(' inc.')]

答案 4 :(得分:0)

由于答案已被接受,所以迟到了派对,但无论如何,这是一个使用Python的内置re模块而不是第三方regex模块的解决方案。

您的尝试正确地将公司名称的末尾锚定在 inc。上,但您需要某种方法来捕获名称的 start 。让我们将公司名称定义为:

  1. 以大写字母或数字开头的单词,后跟
  2. 可选地,一个或多个附加单词,因为公司可能具有单字名称。这些不必以大写字母开头。最后,
  3. INC。
  4. 此外,我们将一个单词定义为一串字母和/或数字,可能包含一个或多个连字符。通常我们会使用\w来表示单词字符,但不包括连字符,所以我们需要单独匹配。

    所以:

    1. 以大写字母或数字开头的单词:[A-Z0-9](?:\w|-)*
    2. 零个或多个附加单词,每个单词表示为:(?:\w|-)+
    3. inc\.
    4. 单词由空格分隔,我们将其表示为\s+。因此,对于#2的“可选的一个或多个单词”,我们必须创建一个包含一个或多个单词字符(包括连字符)后跟一个或多个空格字符的组,并重复该组零次或多次:(?:(?:\w|-)+\s+)* < / p>

      所以,把它们放在一起并在开始时添加\b,确保它以一个完整的单词开头:

      re.findall(r"\b[A-Z0-9](?:\w|-)*\s+(?:(?:\w|-)+\s+)*inc\.", text)
      

      要扩展此功能,您还可以捕获以 Ltd。 Sons 结尾的名称,并同时捕获大写的 Inc。并制作句点可选的:

      re.findall(r"\b[A-Z0-9](?:\w|-)*\s+(?:(?:\w|-)+\s+)*(?:[Ii]nc?|[Ll]td|[Ss]ons)(?:\.|\b)?", text)