【问题标题】:Regex to select certain A tags正则表达式选择某些 A 标签
【发布时间】:2011-05-04 21:05:17
【问题描述】:

我正在尝试创建一个正则表达式模式来提取 html 中在 href 属性中包含特定关键字的 A 标记。

例如,如果我有一个 HTML 块,例如:

<p>Lorem ipsum dolar site amet <a href="http://foo.com">a link</a>. Ut enim ad minim veniam, quis nostrud <a href="http://bar.com">another Link</a>.

如果它的href属性包含关键字“foo”,我如何提取整个A标签(a link)?

任何建议将不胜感激!

【问题讨论】:

    标签: ruby regex


    【解决方案1】:

    除了极其琐碎的用途,regular expressions are discouraged for parsing or manipulating HTML and/or XML。原因是 HTML 和 XML 变化很大,但仍然有效,导致代码中的正则表达式以新奇的方式打破,成为维护nightmare

    这就是你应该为任何超越琐碎应用的事情做这件事:

    require "nokogiri"
    
    html = '
    <p>Lorem ipsum dolar site amet <a href="http://foo.com">link 1</a>. Ut enim ad minim veniam, quis nostrud <a href="http://bar.com">another Link</a>.</p>
    <p>Lorem ipsum dolar site amet <a href="http://bar.com">another link</a>. Ut enim ad minim veniam, quis nostrud <a href="http://foo.com">link 2</a>.</p>
    <p>
      Lorem ipsum dolar site amet <a href="http://bar.com">another link</a>.
      Ut enim ad minim veniam, quis nostrud <a href="http://foo.com">link 3</a>.
    </p>
    <p>
      Lorem ipsum dolar site amet <a href="http://foo.com">link 4</a>.
      Ut enim ad minim veniam, quis nostrud <a href="http://bar.com">another Link</a>.
    </p>
    <p>
      Lorem ipsum dolar site amet <a
        href="http://foo.com"
      >link 5</a>.
      Ut enim ad minim veniam, quis nostrud <a href="http://bar.com">another Link</a>.
    </p>
    '
    
    doc = Nokogiri::HTML(html)
    
    puts doc.search('//a[contains(@href, "foo")]').map{ |n| n.to_s }
    
    >> <a href="http://foo.com">link 1</a>
    >> <a href="http://foo.com">link 2</a>
    >> <a href="http://foo.com">link 3</a>
    >> <a href="http://foo.com">link 4</a>
    >> <a href="http://foo.com">link 5</a>
    

    请注意,解析器能够找到所需&lt;a&gt; 的所有五次出现,尽管我故意破坏了最后一个。这种被破坏的格式是有效的,浏览器理解它不会有问题,但想象一下你尝试生成一个可以捕捉所有这些变化的模式会有多么有趣。

    还要注意,尽管我使用了一个小的 XPath 技巧来在 href 中找到嵌入的 foo,但生成的代码比正则表达式更容易阅读。我一直在做这些东西,并且写了很多正则表达式,并且在将近 30 年后,这些东西仍然伤害了我的眼睛。

    而且,为了避免您认为这只是一个捏造的例子,我在野外遇到过许多看起来像这样的 HTML 和 XML 文件。那里是一片丛林,有一些真实的动物在生成内容。

    【讨论】:

      【解决方案2】:

      如果你必须使用正则表达式,试试这个:

      <a\s+href="(?=[^"]*foo)([^"]*)">([^<]*)
      

      我在网上试了一下:rubular.com

      我正在使用前瞻来查找它是否包含 foo。然后 URL 在第一组中,“链接”在第二组中。

      【讨论】:

      • \s* 不正确。如果缺少空格,它就不是&lt;a&gt; 标签,而是&lt;ahref&gt;,并且无效。删除*,或将其更改为+
      【解决方案3】:

      试试这个:

      /<\s*a[^>]+href\s*=\s*"[^"]*foo[^"]*"[^>]*>.*?<\s*\/a\s*>/
      

      这应该可以解决问题!

      【讨论】:

      • 这是迄今为止最好的+1。 (但不需要\s*开后&lt;
      • 你是对的 ridgerunner! formal XML spec(我不会打扰 SGML,但我怀疑那里是一样的)说在
      【解决方案4】:

      您是否考虑过使用Nokogiri

      【讨论】:

      • "你考虑过使用 Nokogiri 吗?"与其这么说,不如实际说明为什么 Nokogiri 是一种好处。照原样,我很想对答案投反对票,因为您甚至没有尝试过。
      • @the Tin Man:是的,也许我应该将此作为评论而不是答案。我只是想教一个人钓鱼,而不是给他鱼。
      • 我认为重要的是要退后一步,帮助他们理解为什么他们首先要学习钓鱼。一旦他们想学习,教学部分就很容易。
      【解决方案5】:

      这应该可以工作:

      (<a[^>]{0,}?href="([^"]{0,}foo[^"]{0,})"[^>]{0,}>[^<]+</a>)
      

      将捕获整个标签和 href 内容。

      【讨论】:

        猜你喜欢
        • 2018-10-03
        • 1970-01-01
        • 2014-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多