如何分别从两个相同的节点获取内容?

时间:2019-11-14 13:09:27

标签: html ruby xpath nokogiri

我有包含产品名称和价格列表的HTML文件

<ul>
  <li>
    <label>
      <span class="name">Name 1</span>
      <span class="price">3.99</span>
    </label>
  </li>
  <li>
    <label>
      <span class="name">Name 2</span>
      <span class="price">5.49</span>
    </label>
  </li>
...
</ul>

,并且需要分别获取每个<label>中的名称和价格。 我正在使用Nokogiri解析HTML文件并尝试

file.xpath('//ul/li/label').each do |item|
  puts item.content
end

但是,您可能已经猜到了,它会同时返回名称和价格。

2 个答案:

答案 0 :(得分:3)

名称和价格span元素是label元素的子元素,因此您可以在每个xpath范围内使用label来获取它们。

file.xpath('//ul/li/label').each do |item|
  name = item.at_xpath("span[@class='name']").text()
  price = item.at_xpath("span[@class='price']").text()
  puts "#{name} - #{price}"
end

或使用CSS选择器

file.xpath('//ul/li/label').each do |item|
  name = item.at_css('.name').text()
  price = item.at_css('.price').text()
  puts "#{name} - #{price}"
end

答案 1 :(得分:0)

通常我会使用类似这样的东西:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<ul>
  <li>
    <label>
      <span class="name">Name 1</span>
      <span class="price">3.99</span>
    </label>
  </li>
  <li>
    <label>
      <span class="name">Name 2</span>
      <span class="price">5.49</span>
    </label>
  </li>
</ul>
EOT

data = doc.css('label').map { |label| [label.at('.name').text, label.at('.price').text] }.to_h 
# => {"Name 1"=>"3.99", "Name 2"=>"5.49"}

只要.name文本是唯一的(从示例HTML看来应该如此),则生成的哈希将有效且易于使用。

IF 您需要按顺序使用它们,然后如果您对它们进行迭代,则Ruby会以它们最初插入的顺序返回键/值对,这不是我推荐的依据,因为您不能依赖的语言,但您的学习目标可能会有所不同。否则,无论有多少个条目,因为它是一个哈希,因此检索给定键的值的查询都非常快。而且,可以传递散列来进行许多有用的修改。