使用Nokogiri& amp ;;解析和重新格式化数据的最有效方法西纳特拉

时间:2010-11-01 23:34:59

标签: ruby sinatra nokogiri

我正在为一些汽车经销商的库存管理器重新格式化搜索查询的HTML输出。没有直接的数据库访问,服务创建者没有可用的信息,因此我决定尝试使用Nokogiri解析和重新格式化数据,并根据搜索查询生成新的结果页面。

首次加载页面时,我只是使用默认搜索来生成第一个结果。

为了使搜索起作用,我将查询发送到这样的URL:

post '/search/?:search_query' do
  url = "http://domain.com/v/?DealerId=" + settings.dealer_id + "&maxrows=10&#{params[:search_query]}"
  doc = Nokogiri::HTML(open(url))
  doc.css("td:nth-child(5) .ForeColor4").each do |msrp|
    session["msrp"] = msrp.inner_html
  end  
  doc.css("td:nth-child(4) .ForeColor4").each do |price|
    session["price"] = price.inner_html
  end
  erb :index    
end

我知道必须有一个更聪明的方法来做到这一点。

编辑:

请求数据的示例网址:

http://domain.com/?DealerId=1234&object=list&lang=en&MAKE=&MODEL=&maxrows=50&MinYear=&MaxYear=2011&Type=N&MinPrice=&MaxPrice=&STYLE=&ExtColor=&MaxMiles=&StockNo=

生成的HTML的说明:

不幸的是,它的旧代码几乎完全基于表格,具有内联样式,并且在大多数区域中缺少类或ID。

CSS选择器的一个示例:

td:nth-child(5) .ForeColor4

XPath选择器:

//td[(((count(preceding-sibling::*) + 1) = 5) and parent::*)]//*[contains(concat( " ", @class, " " ), concat( " ", "ForeColor4", " " ))]

我也把机械化或hpricot视为可能,但我不知道最好的工具,因为我之前没有尝试过屏幕抓取。

摘要:我想从HTML中提取数据,暂时将其存储在变量/ session / cookie中(数据每天更改几次),然后能够将输出重新格式化为我自己的HTML / CSS样式。

2 个答案:

答案 0 :(得分:1)

就个人而言,我会将刮擦与用户操作分开。有一个独立的过程刮擦并填充您的数据库。这将极大地提高性能,因为提取,创建DOM,解析,然后在每个动作上呈现输出都会变慢。

答案 1 :(得分:0)

  doc.css("td:nth-child(5) .ForeColor4").each do |msrp|
    session["msrp"] = msrp.inner_html
  end  
  doc.css("td:nth-child(4) .ForeColor4").each do |price|
    session["price"] = price.inner_html
  end

您可能希望使用Nokogiri的at_css()方法而不是常规css()at_css()找到目标的第一个匹配项,并且只返回一个节点,类似于对.first返回的节点集执行.css()

这会简化您对此表单的查找:

session["msrp"] = doc.at_css("td:nth-child(5) .ForeColor4").inner_html

我可能会在测试结束时添加类似rescue 'msrp lookup failed'的内容,以防万一你有不好的访问者。或者,当inner_html()试图从零读取时,你可以让代码失败。这只是一种更友好的调试方式。

否则你的查找似乎不错。