为什么这个正则表达式需要这么长时间才能找到某些文件中的电子邮件地址?

时间:2011-11-17 23:03:40

标签: php regex web-scraping

我有一个查找电子邮件地址的正则表达式(这是从我找不到的另一个SO帖子中获取的,并且已经在各种电子邮件配置上进行了测试...更改这不是我的问题...但要明白这是否是根本原因):

/[a-z0-9_\-\+]+@[a-z0-9\-]+\.([a-z]{2,3})(?:\.[a-z]{2})?/i

我在PHP中使用preg_match_all()。

这适用于99.99%的文件我正在查看并需要大约5毫秒,但有时需要几分钟。这些文件大于300k左右的平均网页,但更大的文件通常处理得很好。我能在文件内容中找到的唯一突出的是数千个连续的“随机”字母数字字符串,如下所示:

wEPDwUKMTk0ODI3Nzk5MQ9kFgICAw9kFgYCAQ8WAh4H...

以下是导致问题的两个页面。查看源代码以查看长字符串。

有关导致此问题的任何想法?

- 最终解决方案 -

我测试了答案中建议的各种正则表达式。 @FailedDev的回答有助于将处理时间从几分钟缩短到几秒钟。 @hakre的答案解决了问题并将处理时间缩短到几百毫秒。以下是我使用的最终正则表达式。这是@hakre的第二个建议。

/[a-z0-9_\-\+]{1,256}+@[a-z0-9\-]{1,256}+\.([a-z]{2,3})(?:\.[a-z]{2})?/i

2 个答案:

答案 0 :(得分:8)

您已经知道正则表达式导致大文件出现问题。那么也许你可以让它变得更聪明一点?

例如,您使用+来匹配一个或多个字符。假设你有一串10 000个字符。正则表达式必须看10000个组合才能找到最大的匹配。然后你将它与类似的结合起来。假设你有一个包含20 000个字符和两个+组的字符串。他们怎么能在文件中匹配。可能是10 000 x 10 000种可能性。依此类推。

如果您可以限制字符数(这看起来有点像您正在寻找电子邮件模式),可能会将电子邮件地址域名限制为256,将地址本身限制为256个字符。那么这将是“仅”测试的256 x 256种可能性:

/[a-z0-9_\-\+]{1,256}@[a-z0-9\-]{1,256}\.([a-z]{2,3})(?:\.[a-z]{2})?/i

这可能已经快得多了。然后使这些量词占有率将减少PCRE的回溯:

/[a-z0-9_\-\+]{1,256}+@[a-z0-9\-]{1,256}+\.([a-z]{2,3})(?:\.[a-z]{2})?/i

哪个应该再次加速。

答案 1 :(得分:6)

我最好的猜测是尝试使用积极的量词:

[a-z0-9_\-\+]+

[a-z0-9_\-\+]++

这应该会使正则表达式失败,因此可以在这些情况下提高性能。

编辑:

也许 原子分组也可以提供帮助:

/(?>[a-z0-9_\-+]++)@(?>[a-z0-9\-]++\.)(?>[a-z]{2,3})(?:\.[a-z]{2})?/

你应该先选择第一选项。通过使用选项2看看是否存在任何差异将会很有趣。