3

在 jQuery 中,您可以使用:eq选择器将匹配元素集减少为具有给定索引的元素。

Nokogiri怎么能做同样的事情呢?我找了很久,但找不到方法。

看这个例子:

require 'nokogiri'

html ='
<div>
<p>foo</p></div>
<span>
<p>bar</p>
<p>foobar</p></span>
'

doc = Nokogiri::HTML(html)

p doc.search('p:eq(0)')
# -> []
4

3 回答 3

3

我是这样钓鱼的:

require 'nokogiri'

html ='
<p>foo</p>
<p>bar</p>
<p>foobar</p>
'

doc = Nokogiri::HTML(html)

doc.search('//p[3]')
=> [#<Nokogiri::XML::Element:0x811058ac name="p" children=[#<Nokogiri::XML::Text:0x81104f74 "foobar">]>]

Nokogiri 返回了一个 NodeSet,一个节点集合,其行为类似于一个数组。我可以使用搜索at而不是search仅检索节点:

doc.at('//p[3]').text
=> "foobar"

或者它可以返回 NodeSet,您可以让 Ruby 从中提取特定元素:

doc.search('//p')[2].text
=> "foobar"

p doc.search('p:eq(0)')

'p:eq(0)'不是 CSS,也不是 XPath。这是一个添加到 JavaScript 中的 jQuery 选择器。您不能将 jQuery 或 JavaScript 与 Nokogiri 作为访问器一起使用,它必须是 CSS 或 XPath。


你的例子甚至没有做我想要的。[i] 运算符相当于第 n 个孩子!

根据jQuery 的文档:eq

描述:将匹配元素集减少到指定索引处的元素。

//p[3],或者使用search('p')[2]让 Ruby 对 NodeSet 进行切片,将返回一个特定的节点。在我的示例中,我正在检索第三个<p>标签的内容,它相当于 jQuery 的:eq(2).

使用与之前相同的示例:

require 'nokogiri'

html ='
<p>foo</p>
<p>bar</p>
<p>foobar</p>
'

doc = Nokogiri::HTML(html)

doc.search('//p[0]').text
doc.search('//p[1]').text
doc.search('//p[2]').text
doc.search('//p[3]').text

doc.search('//p')[0].text
doc.search('//p')[1].text
doc.search('//p')[2].text
doc.search('//p')[3].text

将其转储到 IRB 我看到:

irb(main):011:0* doc.search('//p[0]').text # => ""
irb(main):012:0> doc.search('//p[1]').text # => "foo"
irb(main):013:0> doc.search('//p[2]').text # => "bar"
irb(main):014:0> doc.search('//p[3]').text # => "foobar"

irb(main):015:0> doc.search('//p')[0].text # => "foo"
irb(main):016:0> doc.search('//p')[1].text # => "bar"
irb(main):017:0> doc.search('//p')[2].text # => "foobar"
irb(main):018:0> doc.search('//p')[3].text 
NoMethodError: undefined method `text' for nil:NilClass
from (irb):18

Using//p[1]相当于将下面的 HTML 与 JavaScript 和 jQuery 一起使用,将其加载到浏览器中,然后查看显示“foo”的警报:

<html>
  <head>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
  </head>
  <body>
    <p>foo</p>
    <p>bar</p>
    <p>foobar</p>
    <script>
$().ready(function(){
    alert($('p:eq(0)').text());
});
    </script>
  </body>
</html>

因此,在 XPath 或Ruby 中//p使用slice相当于在 JavaScript 中。但是,由于 Nokogiri 不使用 JavaScript 或 jQuery,您必须使用 CSS 或 XPath。[1][0]:eq(0)


jQuery 的选择器现在可用,使这样的事情成为可能:

require 'nokogiri'

html = '
<html>
  <body>
    <p>foo</p>
    this text
    <p>bar</p>
  </body>
</html>
'

doc = Nokogiri::HTML(html)
doc.at('p:contains("foo")').next_sibling.text.strip
=> "this text"
于 2012-11-08T15:19:43.127 回答
0

似乎减少匹配节点集的唯一方法是使用 Ruby 和这样的数组方法:

doc = Nokogiri ... 
doc.search("table")[2].search("...")

Nokogiri 的 XPath 和它的 CSS 选择器都不支持等同于 jQuery:eq运算符的功能。

于 2012-11-11T09:06:21.260 回答
-1

尝试使用 :nth-child(N)(第一个元素是用 N = 1 找到的)

于 2012-11-08T13:38:21.487 回答