使用正则表达式在不在锚中的页面上查找电话号码 [英] Use Regex to find a phone number on a page not in an anchor

查看:79
本文介绍了使用正则表达式在不在锚中的页面上查找电话号码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个正则表达式表达式,用于搜索电话号码模式:

I have this regex expression that searches for a phone number pattern:

[(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4}

这与以下格式的电话号码匹配:

This matches phone numbers in this format:

123 456 7890
(123)456 7890
(123) 456 7890
(123)456-7890
(123) 456-7890
123.456.7890
123-456-7890

我想扫描整个页面(使用JavaScript)以查找此匹配项,但不包括锚点中已存在的此匹配项. 找到匹配项后,我要将电话号码转换为移动设备的点击通话链接:

I want to scan an entire page (with JavaScript) looking for this match, but excluding this match that already exists inside an anchor. After the match is found, I want to convert the phone number into a click to call link for mobile devices:

(123) 456-7890 --> <a href="tel:1234567890">(123) 456-7890</a>

我很确定我需要进行否定查找.我已经尝试过了,但这似乎不是正确的主意:

I'm pretty sure I need to do a negative lookup. I've tried this, but this doesn't seem to be the right idea:

(?!.*(\<a href.*?\>))[(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4}

推荐答案

不要使用正则表达式来解析HTML .使用HTML/DOM解析器获取文本节点(浏览器可以为您过滤文本,删除锚标记以及所有文本太短而无法包含电话号码的文本),您可以直接检查文本.

Don't use regular expressions to parse HTML. Use HTML/DOM parsers to get the text nodes (the browser can filter it down for you, to remove anchor tags and all text too short to contain a phone number for instance) and you can check the text directly.

例如,使用XPath(虽然有点丑陋,但支持以大多数其他DOM方法无法直接处理文本节点的方式):

For example, with XPath (which is a bit ugly, but has support for dealing with text nodes directly in a way most other DOM methods do not):

// This query finds all text nodes with at least 12 non-whitespace characters
// who are not direct children of an anchor tag
// Letting XPath apply basic filters dramatically reduces the number of elements
// you need to process (there are tons of short and/or pure whitespace text nodes
// in most DOMs)
var xpr = document.evaluate('descendant-or-self::text()[not(parent::A) and string-length(normalize-space(self::text())) >= 12]',
                            document.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i=0, len=xpr.snapshotLength; i < len; ++i) {
    var txt = xpr.snapshotItem(i);
    // Splits with grouping to preserve the text split on
    var numbers = txt.data.split(/([(]?\d{3}[)]?[(\s)?.-]\d{3}[\s.-]\d{4})/);
    // split will return at least three items on a hit, prefix, split match, and suffix
    if (numbers.length >= 3) {
        var parent = txt.parentNode; // Save parent before replacing child
        // Insert new elements before existing element; first element is just
        // text before first phone number
        parent.insertBefore(document.createTextNode(numbers[0]), txt);

        // Now explicitly create pairs of anchors and following text nodes
        for (var j = 1; j < numbers.length; j += 2) {
            // Operate in pairs; odd index is phone number, even is
            // text following that phone number
            var anc = document.createElement('a');
            anc.href = 'tel:' + numbers[j].replace(/\D+/g, '');
            anc.textContent = numbers[j];
            parent.insertBefore(anc, txt);
            parent.insertBefore(document.createTextNode(numbers[j+1]), txt);
        }
        // Remove original text node now that we've inserted all the
        // replacement elements and don't need it for positioning anymore
        parent.removeChild(txt);

        parent.normalize(); // Normalize whitespace after rebuilding
    }
}

作为记录,基本过滤器在大多数页面上都可以帮助 lot .例如,在此页面上,就目前而言,据我所见(随用户,浏览器,浏览器扩展和脚本等的不同而不同),如果没有过滤器,则查询'descendant-or-self::text()'的快照将有1794个项目.省略以锚标记为父的文本,'descendant-or-self::text()[not(parent::A)]'会将其降至1538,然后执行完整查询,以验证非空白内容的长度至少为十二个字符,从而将其降至87项.在性能上,将正则表达式应用于87个项是笨拙的更改,并且您不再需要使用不合适的工具来解析HTML.

For the record, the basic filters help a lot on most pages. For example, on this page, right now, as I see it (will vary by user, browser, browser extensions and scripts, etc.) without the filters, the snapshot for the query 'descendant-or-self::text()' would have 1794 items. Omitting text parented by anchor tags, 'descendant-or-self::text()[not(parent::A)]' gets it down to 1538, and the full query, verifying that the non-whitespace content is at least twelve characters long gets it down to 87 items. Applying the regex to 87 items is chump change, performance-wise, and you've removed the need to parse HTML with an unsuitable tool.

这篇关于使用正则表达式在不在锚中的页面上查找电话号码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆