Ruby 如何使用Nokogiri解析连续标记?
我有如下HTML代码:Ruby 如何使用Nokogiri解析连续标记?,ruby,nokogiri,Ruby,Nokogiri,我有如下HTML代码: <div id="first"> <dt>Label1</dt> <dd>Value1</dd> <dt>Label2</dt> <dd>Value2</dd> ... </div> doc = Nokogiri::HTML('<div id="first"><dl>...') doc.css('#first').searc
<div id="first">
<dt>Label1</dt>
<dd>Value1</dd>
<dt>Label2</dt>
<dd>Value2</dd>
...
</div>
doc = Nokogiri::HTML('<div id="first"><dl>...')
doc.css('#first').search('dt').each do |node|
puts "#{node.text}: #{node.next_element.text}"
end
首先显示所有
标记,然后显示
标记,在查看其他答案后,我需要“标签:值”这是一种低效的方法
require 'nokogiri'
a = Nokogiri::HTML('<div id="first"><dt>Label1</dt><dd>Value1</dd><dt>Label2</dt><dd>Value2</dd></div>')
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
需要“nokogiri”
a=Nokogiri::HTML('Label1Value1Label2Value2')
dt=[]
dd=[]
a、 css(“#第一”)。每个do |项|
css(“dt”)。每个{t | dt首先,您的HTML应该在
中包含
和
元素:
只要结构与您的示例相匹配,这应该是可行的。假设某些
可能有多个
,您希望找到所有
,然后(针对每个)在下一个
之前查找以下
。这在纯Ruby中很容易做到,但在XPath中更有趣
鉴于此设置:
require 'nokogiri'
html = '<dl id="first">
<dt>Label1</dt><dd>Value1</dd>
<dt>Label2</dt><dd>Value2</dd>
<dt>Label3</dt><dd>Value3a</dd><dd>Value3b</dd>
<dt>Label4</dt><dd>Value4</dd>
</dl>'
doc = Nokogiri.HTML(html)
使用Lotsa 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"]]
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"]]
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"]]
请注意,由于“#first”
只能匹配一个元素,因此您拥有的元素与:item=a.at_css(“#first”)相等(但更差)
。在外部使用每个
是完全多余的。此外,请注意,此答案假设
和
之间始终存在1-1配对。虽然原始问题标记是如此,但在现实世界的标记中可能并不总是如此。最后,通过迭代两个配对数组,您可以不要考虑使用<代码> Dt.zip(DD)。每个{ dt,d}…} /代码>而不是<代码> EACHYORY索引>代码>,而不是<代码> docs.css('y'第一)。.each?还要注意,这个答案是基于这样一个假设的,即每个
之后总是有一个且只有一个
(这在一般HTML中可能不是这样)。@Phrogz:earch.css没有什么好的理由,也许它更接近OP已经拥有的内容。我确实包括了一个“只要结构与您的示例相匹配,这应该是有效的”警告。我同意您的方法在一般情况下会更有效。(这只是我上一次评论的拼写更正,因为我不知道haz gud speling)
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"]]
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"]]