防止Regex中的灾难性回溯

2024-10-02 10:29:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个代码可以抓取一百万个网站,并从他们的主页上检测出联系信息。在

由于某些原因,当我运行代码时,它会被卡住,在抓取大约60k个请求后无法继续执行,我将数据库中的网站url标记为status=done

我已经运行了几次代码,但它被困在大约60k个请求。在

它不会被困在某个网站上。在

这是我使用的正则表达式

    emails = re.findall('[\w\.-]+@[\w-]+\.[\w\.-]+', lc_body)
    mobiles = re.findall(r"(\(?(?<!\d)\d{3}\)?-? *\d{3}-? *-?\d{4})(?!\d)|(?<!\d)(\+\d{11})(?!\d)", lc_body)
    abns = re.findall('[a][-\.\s]??[b][-\.\s]??[n][-\:\.\s]?[\:\.\s]?(\d+[\s\-\.]?\d+[\s\-\.]?\d+[\s\-\.]?\d+)', lc_body)

    licences = re.findall(r"(Licence|Lic|License|Licence)\s*(\w*)(\s*|\s*#\s*|\s*.\s*|\s*-\s*|\s*:\s+)(\d+)", lc_body, re.IGNORECASE)

我的想法是licences的regex导致了问题,我如何简化它?如何删除回溯?在

我想找到所有可能的牌照号码。在

它可以是License No: 2543License: 2543License # 2543License #2543License# 2543和许多其他组合。在


Tags: 代码re信息数据库url网站licenselicence
1条回答
网友
1楼 · 发布于 2024-10-02 10:29:38

这个问题是由第三组引起的:(\s*|\s*#\s*|\s*.\s*|\s*-\s*|\s*:\s+)-这里所有的备选方案都以\s*开头。这会导致大量冗余回溯,因为这些替代项可以在字符串中的同一位置匹配。最佳实践是在备选方案组中使用在同一位置不匹配的备选方案。

现在,看看需要匹配的字符串,我建议使用

Lic(?:en[cs]e)?(?:\W*No:)?\W*\d+

参见regex demo

使模式更具体、更线性,尽可能多地去掉alternations,使用optional non-capturing groups和字符类。在

详细信息

  • Lic(?:en[cs]e)?-Lic后跟1或0次出现(由于?量词与ence或{}的量化子模式匹配,因此(?:...)?是可选的non-capturing group(字符类[sc]匹配s或{},比(s|c)有效得多)
  • (?:\W*No:)?-一个非捕获组,匹配1个或0个出现的0+非单词字符(带有\W*),后跟No:子字符串
  • \W*
  • \d+-1个或多个数字。在

相关问题 更多 >

    热门问题