如何用Nokogiri解析连续标签?

我有这样的HTML代码:

Label1
Value1
Label2
Value2
...

我的代码不起作用。

 doc.css("first").each do |item| label = item.css("dt") value = item.css("dd") end 

显示所有

标签第一,然后显示

标签,我需要“标签:值”

首先,您的HTML应该在

包含

元素:

 
Label1
Value1
Label2
Value2
...

但这不会改变你解析它的方式。 你想找到

并迭代它们,然后在每个

你可以使用next_element来获得

; 像这样的东西:

 doc = Nokogiri::HTML('
...') doc.css('#first').search('dt').each do |node| puts "#{node.text}: #{node.next_element.text}" end

只要结构与您的示例匹配,这应该有效。

假设某些

可能有多个

,您希望找到所有

,然后(对于每个)在下一个

之前找到以下

。 这在纯Ruby中非常容易,但在XPath中更有趣。 ;)

鉴于此设置:

 require 'nokogiri' html = '
Label1
Value1
Label2
Value2
Label3
Value3a
Value3b
Label4
Value4
' doc = Nokogiri.HTML(html)

不使用XPath

 doc.css('dt').each do |dt| dds = [] n = dt.next_element begin dds << n n = n.next_element end while n && n.name=='dd' p [dt.text,dds.map(&:text)] end #=> ["Label1", ["Value1"]] #=> ["Label2", ["Value2"]] #=> ["Label3", ["Value3a", "Value3b"]] #=> ["Label4", ["Value4"]] 

使用Little XPath

 doc.css('dt').each do |dt| dds = dt.xpath('following-sibling::*').chunk{ |n| n.name }.first.last p [dt.text,dds.map(&:text)] end #=> ["Label1", ["Value1"]] #=> ["Label2", ["Value2"]] #=> ["Label3", ["Value3a", "Value3b"]] #=> ["Label4", ["Value4"]] 

使用Lotsa XPath

 doc.css('dt').each do |dt| ct = dt.xpath('count(following-sibling::dt)') dds = dt.xpath("following-sibling::dd[count(following-sibling::dt)=#{ct}]") p [dt.text,dds.map(&:text)] end #=> ["Label1", ["Value1"]] #=> ["Label2", ["Value2"]] #=> ["Label3", ["Value3a", "Value3b"]] #=> ["Label4", ["Value4"]] 

看完其他答案后,这是一种做同样事情的低效方法。

 require 'nokogiri' a = Nokogiri::HTML('
Label1
Value1
Label2
Value2
') dt = [] dd = [] a.css("#first").each do |item| item.css("dt").each {|t| dt << t.text} item.css("dd").each {|t| dd << t.text} end dt.each_index do |i| puts dt[i] + ': ' + dd[i] end

在css中引用ID需要先放入#符号。 对于一个类,它是。 符号。

Interesting Posts