我使用CSS选择了使用XPath作为他们更可读的粉丝:
require 'nokogiri'
doc = Nokogiri::HTML('<link rel="canonical" href="https://test.com/somepage">')
doc.at('link[rel="canonical"]')['href'] # => "https://test.com/somepage"
什么引入nokogiri和XPath,被访问节点参数时返回
还有的来混淆。试想一下:
require 'nokogiri'
doc = Nokogiri::HTML('<link rel="canonical" href="https://test.com/somepage">')
这是我怎么会做它用CSS:
doc.at('link[rel="canonical"]').class # => Nokogiri::XML::Element
doc.at('link[rel="canonical"]')['href'].class # => String
doc.at('link[rel="canonical"]')['href'] # => "https://test.com/somepage"
的XPath,而功能更强大,也能够让你,或者引入nokogiri,Ruby或CPU的,做多工作。
首先,xpath
是search
的XPath特定版本,它返回一个NodeSet,而不是节点或元素。一个NodeSet类似于一组节点,如果你不知道你有什么,它会咬你。从NodeSet文档:
NodeSet包含Nokogiri :: XML :: Node对象的列表。通常,一个节点集是回报通过引入nokogiri搜索文档:: XML ::检索#CSS或引入nokogiri :: XML ::检索#XPath的
如果你正在寻找一个特定节点,或仅一个的结果特定类型的节点的单个实例,然后使用at
,或者如果您想要挑剔,请使用at_css
或at_xpath
。 (Nokogiri在使用at
或search
时通常会弄清楚你的意思,但有时你必须使用特定的方法让Nokogiri在正确的方向上微调)。在上面的例子中使用at
表明它返回节点本身,并且一旦你已经得到了节点,通过把它看作一个散列来获得任何参数的值是微不足道的。
xpath
,search
和css
都返回节点集,所以,像一个数组,你需要指向实际的元素,那么你想获得的参数:
doc.xpath('//link[@rel="canonical"]/@href').class # => Nokogiri::XML::NodeSet
doc.xpath('//link[@rel="canonical"]/@href').first.class # => Nokogiri::XML::Attr
doc.xpath('//link[@rel="canonical"]/@href').text # => "https://test.com/somepage"
注意'//link[@rel="canonical"]/@href'
导致引入nokogiri返回获得Attr对象,而不是文本。您可以打印该对象,并且Ruby将对其进行字符串化,但如果您尝试像对待它一样对待它,它将不会像字符串那样表现出错误,从而导致错误。例如:
doc.xpath('//link[@rel="canonical"]/@href').first.downcase # => NoMethodError: undefined method `downcase' for #<Nokogiri::XML::Attr:0x007faace115d20>
相反,使用text
或content
来获取文本值:
doc.at('//link[@rel="canonical"]/@href').class # => Nokogiri::XML::Attr
doc.at('//link[@rel="canonical"]/@href').text # => "https://test.com/somepage"
或获取元素本身,然后访问像你该参数将哈希:
doc.at('//link[@rel="canonical"]').class # => Nokogiri::XML::Element
doc.at('//link[@rel="canonical"]')['href'] # => "https://test.com/somepage"
其中之一将返回一个字符串。
另请注意,在此示例中,我没有使用@href
返回Attr,我只获取节点本身,然后使用['href']
返回参数的文本。这是一个较短的选择器,至少对我来说更有意义,因为Nokogiri不必返回Attr对象,然后您必须使用text
进行转换,否则当您不小心将其视为字符串时,可能会遇到问题。
'canon'不会是一个字符串,它将是一个Attr对象,它不会像字符串那样操作。当你使用'puts'的时候它会被字符串化,但是如果你试图把它当作任何东西而不是它是什么,它就会遮住真正的对象,这会引起问题。 –
重点是,它会grep什么。 '加农炮'就是为了证明它。 –