【问题标题】:Regex to parse links containing specific words正则表达式解析包含特定单词的链接
【发布时间】:2010-02-01 08:11:02
【问题描述】:

this 线程更进一步,有人能告诉我这两个正则表达式有什么区别吗?他们似乎都完成了同样的事情:从 html 中提取链接。

表达式 1:

'/(https?://)?(www.)?([a-zA-Z0-9_%]*)\b.[a-z]{2,4}(.[a-z]{2})?((/[a-zA-Z0-9_%])+)?(.[a-z])?/'

表达式 2:

'/<a.*?href\s*=\s*["\']([^"\']+)[^>]*>.*?<\/a>/si'

哪个更好用?我如何修改其中一个表达式以仅匹配包含某些单词的链接,并忽略任何不包含这些单词的匹配项?

谢谢。

【问题讨论】:

    标签: php regex parsing


    【解决方案1】:

    不同之处在于表达式 1 按照规范查找有效且完整的 URI。因此,您可以获得代码内部某处的所有完整 url。这实际上与获取所有链接无关,因为它与经常使用的相对 url 不匹配,并且它获取每个 url,而不仅仅是链接目标的那些。

    第二个查找a 标签并获取href 属性的内容。所以这个会给你每个链接。除了该表达式中的一个错误*,使用它是非常安全的,它可以很好地获取每个链接 - 它会检查可能出现的足够差异,例如空格或其他属性。

    *但是,该表达式有一个错误,因为它不查找 href 属性的右引号,您应该添加它,否则您可能会匹配奇怪的东西:

    /<a.*?href\s*=\s*["\']([^"\'>]+)["\'][^>]*>.*?<\/a>/si
    

    根据评论进行编辑:

    要在链接 url 中查找 word,请使用:

    /<a.*?href\s*=\s*["\']([^"\'>]*word[^"\'>]*)["\'][^>]*>.*?<\/a>/si
    

    要在链接文本中查找word,请使用:

    /<a.*?href\s*=\s*["\']([^"\'>]+)["\'][^>]*>.*?word.*?<\/a>/si
    

    【讨论】:

    • 太棒了,感谢您的解释。现在假设我想修改第二个表达式以匹配包含单词 blue、red 或 green(链接中的任何位置)的链接,并忽略不包含这些词之一的链接。这可能吗?
    • 做到了.. 最后一个问题,多个单词的语法是什么?功能如下: "/]*red,green,blue[^"\'>]*) ["\'][^>]*>.*?/si" 搜索正则表达式是一场噩梦。再次感谢戳。
    • 如果你想匹配“红色”或“蓝色”,这样做:(red|blue);如果您不想匹配该部分本身,也可以使用(?:red|blue)
    • 嗯,你是对的。我会把我的错误评论归咎于睡眠不足。评论已删除。
    【解决方案2】:

    在大多数情况下,我强烈建议使用 HTML 解析器(例如 this one)来获取这些链接。使用正则表达式来解析 HTML 会出现问题,因为 HTML 不是正则的,而且您将无法考虑边缘情况。

    请参阅here 了解更多信息。

    【讨论】:

    • 我不同意,匹配格式良好的链接并不太难,通过正则表达式进行匹配的开发时间只是解析器的一小部分。他甚至没有尝试解析 HTML,他正在解析可能包含链接的文本。
    • 虽然我接受你的观点。实用主义(我已经修改了我的答案以反映这一点),他在上面确实说过正则表达式正在从 HTML 中提取链接。
    • 它是从 Wordpress 帖子的内容中提取出来的,所以它会是 HTML(对吗?),但它是非常干净的 HTML。使用正则表达式对我来说似乎工作得很好,我只是想确保我使用的表达式会给我带来最好的结果。解析器很有趣,感谢您的链接。
    • 在像您这样的封闭/已知案例中,正则表达式并非不合理。但值得关注解析器的发展。
    • 我不知道为什么人们对使用真正的解析器如此谨慎。这是正确处理 HTML 的唯一方法,而且并不难。 (编写一个解析器,当然,很难;使用一个,微不足道。)想出一个正则表达式来处理链接语法的常见变体是非常困难的,而且在一般情况下是不可能的。您是否希望您正在抓取的页面上的链接格式始终保持完全相同?您不会被脚本块内容中的注释掉的链接或 HTML 愚弄吗?链接元素分成多行?
    【解决方案3】:
    /<a.*?href\s*=\s*["']([^"']+)[^>]*>.*?<\/a>/si
    

    你必须非常小心.*,即使是非贪婪形式。 . 很容易匹配到超出您预期的内容,尤其是在 dotall 模式下。例如:

    <a name="foo">anchor</a>
    <a href="...">...</a>
    

    从第一个 &lt;a 的开头匹配到第二个的结尾。

    更不用说以下情况了:

    <a href="a"></a >
    <a href="b"></a>
    

    或:

    <a href="a'b>c">
    

    或:

    <a data-href="a" title="b>c" href="realhref">
    

    或:

    <!-- <a href="notreallyalink"> -->
    

    还有更多有趣的边缘案例。您可以尝试优化您的正则表达式以捕捉更多可能性,但您永远无法全部获得,因为 HTML 无法用正则表达式解析(告诉您的朋友)!

    HTML+regex 是傻瓜游戏。帮自己一个忙。使用 HTML 解析器。

    【讨论】:

    • +1。我注意到标记语法突出显示本身被上面的内容弄糊涂了,我敢打赌,某个地方涉及到一个正则表达式!
    • 是的! SO 的语法高亮是一个高度复杂的正则表达式。它不能真正正确地解析 HTML 或 XML(即使它想在 JS 中包含一个完整的 HTML 解析器),因为它甚至不知道上面的代码块是 HTML! SO 对它进行了很好的猜测,令人印象深刻的是它的表现和它一样好,但它永远无法真正做到正确。但这没关系,因为它只是用于一些着色,而不是任何重要的东西。
    【解决方案4】:

    乍一看,第一个是垃圾,但似乎试图将链接匹配为文本,第二个是匹配 html 元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 1970-01-01
      • 2012-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多