我正在尝试抓取电子邮件地址的网页。我几乎有它工作,但似乎有一些巨大的内存错误,使我的脚本加载时页面冻结。
这就是我所拥有的:
var bodyText = document.body.textContent.replace(/\n/g, " ").split(' '); // Location to pull our text from. In this case it's the whole body
var r = new RegExp("[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])", 'i');
function validateEmail(string) {
return r.test(string);
}
var domains = [];
var domain;
for (var i = 0; i < bodyText.length; i++){
domain = bodyText[i].toString();
if (validateEmail(domain)) {
domains.push(domain);
}
}
我唯一能想到的是我使用的电子邮件验证功能是一个32步表达式,page I'm running it on返回超过3,000个部分,但我觉得这应该是可能的。< / p>
这是一个重现错误的脚本:
var str = "help.yahoo.com/us/tutorials/cg/mail/cg_addressguard2.html";
var r = new RegExp("[a-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])", 'i');
console.log("before:"+(new Date()));
console.log(r.test(str));
console.log("after:"+(new Date()));`
我可以做些什么来克服内存问题?
答案 0 :(得分:4)
stribizhev已在评论中指出了解决方案:在RegExp literal 语法中指定正则表达式。正如sln的评论所示,另一个解决方案是正确转义字符串文字中的\
。
我不会说明在这个答案中使用正则表达式验证/匹配电子邮件地址的正确正则表达是什么,因为它已经多次重新进行了重复。
为了演示导致问题的原因,让我们将传递给RegExp构造函数的字符串打印到控制台。您是否注意到某些\
丢失了?
[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])
^ ^ ^ ^
上面的字符串是RegExp构造函数看到并编译的内容。
/
只需要在RegExp文字中进行转义(因为RegExp文字由/
分隔),并且不需要在字符串传递中转义到RegExp构造函数因此,遗漏不会引起任何问题。
以下是显示如何编写正则表达式以使/
与RegExp文字和RegExp构造函数匹配的等效示例:
/\//;
new RegExp("/");
但是,由于\
中的\.
未在字符串中正确转义,而不是匹配文字.
,因此它允许任何字符(行分隔符除外)匹配。
因此,从完全正确的解决方案来看,正则表达式中的这些部分遭受了灾难性的回溯:
(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*
(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+
由于.
可以匹配任何字符,因此上面的片段会退化为典型的灾难性回溯模式(A*)*
。通过将正则表达式的权力降低到其严格的子集,您可以更清楚地看到问题:
(?:a[a]+)*
(?:[a](?:[a]*[a])?a)+
这是使用RegExp文字的解决方案,它与问题中字符串文字中指定的相同。你正确地完成了RegExp文字的转义,但是在RegExp构造函数中使用它:
var r = /[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])/i;
至于等效的RegExp构造函数解决方案:
var r = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])", "i");
答案 1 :(得分:1)
不完全是您问题的答案,但您首先需要做的是减少必须使用&#34;更正&#34;来测试的文本部分的数量。图案。在您的html示例文件中,您有大约3300个文本字符串要使用正则表达式进行测试。请记住,使用正则表达式会产生成本,因此删除无用的文本部分是一个优先事项:
var textParts = document.body.textContent
.split(/\s+/) // see the note
.filter(function(part) {
return part.length > 4 && part.length < 255 && part.indexOf('@') > 1;
});
alert(textParts.join("\n"));
现在你只有大约50个文本部分需要测试。
注意:如果您想接收双引号内有空格的帐户电子邮件地址,可以尝试更改:
.split(/\s+/)
到
.split(/(?=[\s"])((?:"[^"\n\\]*(?:\\.[^"\n\\]*)*"[^"\s]*)*)(?:\s+|$)/)
(不作任何保证)
关于你的模式:你的模式中的错误已经被其他答案和评论所指出,但请注意,你可以用这个更快地获得相同的结果(相同的匹配):
/\b\w[!#-'*+\/-9=?^-~-]*(?:\.[!#-'*+\/-9=?^-~-]+)*@[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z0-9]+(?:[-.][a-z0-9]+)*\b/i
答案 2 :(得分:0)
这是一个不太严格的正则表达式的例子,速度很快。
ALTER TABLE user_data
PARTITION (name = 'ABC')
SET LOCATION = 'db/partitions/new';
function getEmails(str) {
var r = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/ig;
var emails = [];
var e = null;
var n = 0;
while ((e = r.exec(str)) !== null) {
emails[n++] = e[0];
}
return emails;
}
function emailTest() {
var str = document.getElementsByTagName('body')[0].innerHTML;
var emails = getEmails(str);
document.getElementById('found').innerHTML=emails.join("\n");
}
emailTest();
#found {
color:green;
font-weight:bold;
}