我如何在python中纠正这个Regex电话号码提取器



当我将一组英国电话号码复制到剪贴板后运行此操作时,我得到的结果以一种非常奇怪的方式出现。(在你问之前我已经导入了两个模块)

phoneRegex = re.compile(r'''(
    (d{5}|(d{5}))?       #area code
    (s|-|.)?               #separator
    (d{6})                  #main 6 digits
    )''', re.VERBOSE)
emailRegex = re.compile(r'''(
    [a-zA-Z0-9._%+-]+        #username
    @                        #obligatory @ symbol
    [a-zA-Z0-9.-]+           #domain name
    (.[a-zA-Z]{2,5})        #dot-something
    )''', re.VERBOSE)
text = str(pyperclip.paste())
matches = []
for groups in phoneRegex.findall(text):
    phoneNum = '-'.join([groups[1], groups[3]])
    if groups[3] != '':
        phoneNum += ' ' + groups[3]
    matches.append(phoneNum)
for groups in emailRegex.findall(text):
    matches.append(groups[0])
if len(matches) > 0:
    pyperclip.copy('n'.join(matches))
    print('Copied to clipboard:')
    print('n'.join(matches))
else:
    print('No phone numbers or email addresses found')

错误在这里:

for groups in phoneRegex.findall(text):
    phoneNum = '-'.join([groups[1], groups[3]])
    if groups[3] != '':
        phoneNum += ' ' + groups[3]
    matches.append(phoneNum)

复制到剪贴板的数字:
07338 754433
01265768899
(01283) 657899

预期结果:
复制到剪贴板:
07338 754433
01265 768899
01283 657899

返回结果:
复制到剪贴板:
07338 - 754433 754433
-012657 012657
(01283) -657899 657899

我看到三个问题:

  1. python代码将电话号码的两个部分与-连接在一起,然后再添加一个空格和第三部分:

        phoneNum = '-'.join([groups[1], groups[3]])
        if groups[3] != '':
            phoneNum += ' ' + groups[3]
    

    由于groups[3]将永远不是空白的,您需要做的是:

        if groups[1] != '':
            phoneNum = ' '.join(groups[1], groups[3])
        else:
            phoneNum = groups[3]
    
  2. 您的phoneRegex正则表达式不锚定到行的开始和结束。您需要(a)使用re.MULTILINE选项编译它,(b)在^$之间锚定正则表达式:

    phoneRegex = re.compile(r'''^(
        (d{5}|(d{5}))?       #area code
        (s|-|.)?               #separator
        (d{6})                  #main 6 digits
        )$''', re.VERBOSE + re.MULTILINE)
    

    这将防止没有分隔符的长串数字只是第3组后面有一堆数字。

  3. 您对区号的匹配包括组匹配中的匹配括号。要解决这个问题,您要么需要更改正则表达式以确保括号不是组的一部分,要么需要更改代码以在需要时去掉括号。

    • 避免在正则表达式中使用括号:

          (?:(d{5})|((d{5})))?       #area code
      

      (?:...)是圆括号的非分组形式,因此find不会返回它。在其中,您有两种选择:一组中的5位数字- (d{5}) -或将5位数字包含在一组中的文字括号- ((d{5}))

      然而,这个变化也会影响你的电话号码重组逻辑,因为你的区号是groups[1]groups[2],而你的主号码现在在groups[4]中。

          if groups[1] != '':
              phoneNum = ' '.join(groups[1], groups[4])
          elif groups[2] != '':
              phoneNum = ' '.join(groups[2], groups[4])
          else:
              phoneNum = groups[4]
      
      • 可以通过将外部括号集和分隔符周围的括号更改为非分组括号来简化此操作。然后,您可以对组的过滤结果执行单个连接:

        phoneRegex = re.compile(r'''(?:
            (?:(d{5})|((d{5})))?       #area code
            (?:s|-|.)?               #separator
            (d{6})                  #main 6 digits
            )''', re.VERBOSE)
        # ...
            phoneNum = ' '.join([group for group in groups if group != ''])
        

        修改后的phoneRegex确保返回的groups只包含groups[0]groups[1]中的可选区号,后跟groups[2]中的主号码,不返回多余的匹配。然后,代码过滤掉任何空的组,并返回由空格连接的其余组。

    • 去掉代码中的括号:

          if groups[1] != '':
              phoneNum = ' '.join(groups[1].lstrip('(').rstrip(')'), groups[3])
          else:
              phoneNum = groups[3]
      

最新更新