基于先前断开连接的HTML元素匹配DOM节点的子集

时间:2012-05-22 10:07:55

标签: ruby csv nokogiri mechanize

我试图进入CSV数据库/ Ruby数组的页面列出了470个不均匀大小的组的记录,每个组前面都有一个日期(总共22个唯一日期)。

我不知道该怎么做,因为组没有组织成任何HTML表,也没有任何层次结构在DOM中,“父”可能导致每个组的日期,只有<div class="line">的干燥列表可见记录div,偶尔只有一个<span class="date">Thursday, May 24, 2012</span>,只保留一个仅适用于下一个X记录的日期,直到打印出新的日期为止。

irb中,它正确显示:

$page = $agent.get(pageurl) # gets page with Mechanize
doc = $page.parser # returns Nokogiri::HTML 

(records = doc.search('html body div#wrapper div#innerwrapper div#content div.line')).size 
=> 470
(dates = doc.search('html body div#wrapper div#innerwrapper div#content span.date')).size 
=> 22

显示第一个日期例如:

doc.search('html body div#wrapper div#innerwrapper div#content span.date')[0].text
=> "Wednesday, May 23, 2012"

我的目标是在保存到CSV文件之前,将正确的日期作为字段附加到上面找到的470个记录 doc.search中的每一个。

Nokogiri(或Mechanize)可以帮助我根据他们在DOM中的位置分组检索这些记录,即紧跟dates[N].text之后但在下一个<span class="date">之前?

对于所有470条记录,我可以从0到21迭代N,附加到主数组/ CSV对象,但对于每个组,添加相应的date字段。

2 个答案:

答案 0 :(得分:1)

首先,您可以稍微简化搜索。由于内容是id,并且根据定义唯一标识该特定div,因此您不需要任何前面的路径信息。

records = doc.search('div#content div.line')

您可以使用xpath的preceding-sibling轴从每条记录中提取日期。共:

doc.search('div#content div.line').each do |record|
  date = record.xpath('preceding-sibling::span[@class="date"][1]').text
  #append to CSV
end

XPath说:找到具有“date”(preceding-sibling::span)类的同一级别([@class="date"])的前面跨度,并取第一个这样的跨度([1] )以确保您获得最近的日期范围。)

答案 1 :(得分:1)

这是使用遍历的另一个好时机:

doc.traverse do |node|
  @date = node.text if 'span' == node.name && 'date' == node[:class]
  puts [@date, node.text].join(', ') if 'div' == node.name && 'line' == node[:class]
end