我想在这样的文档中获得所有*.html
链接。
require 'open-uri'
page = Nokogiri::HTML(open "http://example.com")
page.xpath("//a/@href").map{|item| item.value if item.value =~ /.*.html$/ }.compact
我可以用xpath
方法实现相同的功能吗?我想如果可能的话会简单很多。
最简单的方法是使用Ruby的URI类并使用extract
方法:
require 'uri'
html = '
<html>
<body>
http://foo.bar.com
mailto://foo@bar.com
</html>
'
URI.extract(html) # => ["http://foo.bar.com", "mailto://foo@bar.com"]
不解析HTML,而是使用正则表达式查找类似url的模式。这有点容易出错,但简单快捷。
除此之外,很容易在XML中导航并找到url 如果你知道它们在哪里,否则你只是在黑暗中拍摄,应该使用像URI.extract
这样的东西,因为它经过了良好的测试,有许多模式可以识别,并允许您自定义想要找到的内容。不使用它会让你重新发明轮子。
您的测试,寻找a/@href
将找到锚与href
参数,但这些不一定是url,因为JavaScript动作也可以住在那里。
如果使用Nokogiri,只想在<a>
href中查看,我会这样做:
require 'nokogiri'
html = '
<html>
<body>
<p><a href="http://foo.bar.com/index.html">foo</a></p>
<p><a href="mailto://foo@bar.com">bar</a></p>
</html>
'
doc = Nokogiri::HTML(html)
doc.search('a[href]').select{ |n| n['href'][/.html$/] }.map{ |n| n['href'] }
# => ["http://foo.bar.com/index.html"]
它使用CSS而不是XPath,这通常会产生更可读的选择器。
n['href']
是获取节点参数值的Nokogiri简写。
[.html$/]
是一个字符串快捷方式,用于对该字符串应用regex匹配。
看你写的东西:
page.xpath("//a/@href").map{|item| item.value if item.value =~ /.*.html$/ }.compact
由于map
中的if
条件,您必须使用compact
来清除数组中不需要的/意外的nil
值。不要那样做;当你不需要这样写的时候,它就是反动的和防御性的编程。相反,使用select
或reject
来处理条件测试,然后只将可接受的节点提供给map
,然后将它们转换:
doc.search('a[href]').select{ |n| n['href'][/.html$/] }.map{ |n| n['href'] }