正则表达式选择某些A标签

时间:2011-05-04 21:05:18

标签: ruby regex

我正在尝试创建一个正则表达式模式来提取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)?

非常感谢任何建议!

5 个答案:

答案 0 :(得分:3)

除了极其微不足道的用途,regular expressions are discouraged for parsing or manipulating HTML and/or XML。原因是HTML和XML可能会有很大差异,并且仍然有效,导致代码中的正则表达式以新的和奇妙的方式中断,成为维护nightmare

除了简单的app之外,你应该如何做到这一点:

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>

请注意,解析器能够找到所需的<a>的所有五个匹配项,即使我故意破坏了最后一个。那种受损的格式是有效的,浏览器在理解它时没有任何问题,但想象一下你试图生成一个可以捕获所有这些变化的模式的乐趣。

另请注意,尽管我在href中找到了一个小的XPath技巧来找到嵌入的foo,但结果代码比正则表达式更容易阅读。我已经做了很长时间了,写了很多正则表达式,并且在接近30年之后,这些东西仍然伤害了我的眼睛。

而且,为了避免您认为这只是一个简单的例子,我在野外遇到了许多HTML和XML文件。这是一个丛林,有一些真正的动物产生内容。

答案 1 :(得分:2)

试试这个:

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

这应该可以做到!

答案 2 :(得分:1)

您是否考虑过使用Nokogiri

答案 3 :(得分:1)

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

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

我在网上尝试过:rubular.com

我正在使用前瞻来查找它是否包含foo。然后,URL位于第一组中,“a link”位于组2中。

答案 4 :(得分:0)

这应该有效:

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

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