如何使用正则表达式从HTML中提取链接?

时间:2009-02-08 00:17:20

标签: ruby regex

我想从google.com中提取链接;我的HTML代码如下所示:

<a href="http://www.test.com/" class="l"

我花了大约五分钟找到一个使用www.rubular.com工作的正则表达式。 它是:

"(.*?)" class="l"

代码是:

require "open-uri"
url = "http://www.google.com/search?q=ruby"

source = open(url).read()
links = source.scan(/"(.*?)" class="l"/) 

links.each { |link| puts #{link} 
}

问题是,是不是输出了网站链接。

3 个答案:

答案 0 :(得分:4)

这些链接实际上有class=l而不是class="l"。顺便说一下,为了计算这个问题,我在方法中添加了一些日志记录,以便您可以在各个阶段查看输出并进行调试。我搜索了你期望找到的字符串但没找到它,这就是你的正则表达式失败的原因。所以我找了你想要的正确字符串并相应地更改了正则表达式。调试技巧很方便。

require "open-uri"
url = "http://www.google.com/search?q=ruby"

source = open(url).read

puts "--- PAGE SOURCE ---"
puts source

links = source.scan(/<a.+?href="(.+?)".+?class=l/)

puts "--- FOUND THIS MANY LINKS ---"
puts links.size

puts "--- PRINTING LINKS ---"
links.each do |link|
  puts "- #{link}"
end

我也改进了你的正则表达式。您正在寻找一些以打开标记(<a)开头的文本,然后是您不关心的某些字符(.+?),一个href属性({{1} }),要捕获的href属性的内容(href="),一些空格或其他属性((.+?)),最后是类attrubute(.+?)。

我在那里有三个地方class=l.+?表示任何字符,.表示必须有一个或多个字符,而+表示?应该尝试匹配尽可能短的字符串。

答案 1 :(得分:2)

说穿了,问题是你正在使用正则表达式。问题是HTML就是所谓的context-free language,而正则表达式只能是regular languages所谓的语言类。

您应该做的是将页面数据发送到可以处理HTML代码的解析器,例如Hpricot,然后遍历从解析器获得的解析树。

答案 2 :(得分:0)

  

我出了什么问题?

您正在尝试使用正则表达式解析HTML。不要那样做。正则表达式无法覆盖即使是有效的XHTML所允许的语法范围,更不用说现实世界的标签汤了。使用HTML解析器库,例如Hpricot。

FWIW,当我获取“http://www.google.com/search?q=ruby”时,我在返回的标记中的任何地方都没有收到“class =”l“'。也许这取决于您使用的是哪个本地Google和/或您是否已登录或拥有Google Cookie。 (你的脚本和我一样,不会。)