Ruby 使用Nokogiri和需要JSON输出的刮表

Ruby 使用Nokogiri和需要JSON输出的刮表,ruby,screen-scraping,nokogiri,watir,page-object-gem,Ruby,Screen Scraping,Nokogiri,Watir,Page Object Gem,因此,我有一个包含多行和多列的表 <table> <tr> <th>Employee Name</th> <th>Reg Hours</th> <th>OT Hours</th> </tr> <tr> <td>Employee 1</td> <td>10</td> <

因此,我有一个包含多行和多列的表

<table>
  <tr>
    <th>Employee Name</th>
    <th>Reg Hours</th>
    <th>OT Hours</th>
  </tr>
  <tr>
    <td>Employee 1</td>
    <td>10</td>
    <td>20</td>
  </tr>
  <tr>
    <td>Employee 2</td>
    <td>5</td>
    <td>10</td>
  </tr>
</table>
编辑:

使用页面对象gem和@Dave_McNulla的链接,我尝试了这段代码,只是想看看我得到了什么:

class MyPage
  include PageObject

  table(:report, :id => 'UC255_tblSummary')

  def get_some_information
    report_element[1][2].text
  end
end

puts get_some_information
但是,什么也没有归还

数据:


有一份工时表的副本。第一个很好。需要的另一个表是附件收入表。(我还需要activations表,但我将尝试从合并小时和附件收入表的代码中合并该表。

我认为一般方法是:

  • 为键为employee的每个表创建哈希
  • 将两个表的结果合并在一起
  • 转换为JSON
  • 为键为员工的每个表创建一个哈希值

    这部分可以在Watir或Nokogiri中完成。只有在Watir由于表太大而导致性能不佳时,使用Nokogiri才有意义

    瓦蒂尔:

    #I assume you would have a better way to identify the tables than by index
    hours_table = browser.table(:index, 0)
    wage_table = browser.table(:index, 1)
    
    #Turn the tables into a hash
    employee_hours = {}
    hours_table.trs.drop(1).each do |tr| 
        tds = tr.tds
        employee_hours[ tds[0].text ] = {"Reg Hours" => tds[1].text, "OT Hours" => tds[2].text}     
    end
    #=> {"Employee 1"=>{"Reg Hours"=>"10", "OT Hours"=>"20"}, "Employee 2"=>{"Reg Hours"=>"5", "OT Hours"=>"10"}}
    
    employee_wage = {}
    wage_table.trs.drop(1).each do |tr| 
        tds = tr.tds
        employee_wage[ tds[0].text ] = {"Revenue" => tds[1].text}   
    end
    #=> {"Employee 2"=>{"Revenue"=>"$10"}, "Employee 1"=>{"Revenue"=>"$50"}}
    
    诺科吉里:

    page = Nokogiri::HTML.parse(browser.html)
    
    hours_table = page.search('table')[0]
    wage_table = page.search('table')[1]
    
    employee_hours = {}
    hours_table.search('tr').drop(1).each do |tr| 
        tds = tr.search('td')
        employee_hours[ tds[0].text ] = {"Reg Hours" => tds[1].text, "OT Hours" => tds[2].text}     
    end
    #=> {"Employee 1"=>{"Reg Hours"=>"10", "OT Hours"=>"20"}, "Employee 2"=>{"Reg Hours"=>"5", "OT Hours"=>"10"}}
    
    employee_wage = {}
    wage_table.search('tr').drop(1).each do |tr| 
        tds = tr.search('td')
        employee_wage[ tds[0].text ] = {"Revenue" => tds[1].text}   
    end
    #=> {"Employee 2"=>{"Revenue"=>"$10"}, "Employee 1"=>{"Revenue"=>"$50"}}
    
    将两个表的结果合并在一起

    您希望将这两个哈希合并在一起,以便对于特定员工,哈希将包括他们的工作时间和收入

    employee = employee_hours.merge(employee_wage){ |key, old, new| new.merge(old) }
    #=> {"Employee 1"=>{"Revenue"=>"$50", "Reg Hours"=>"10", "OT Hours"=>"20"}, "Employee 2"=>{"Revenue"=>"$10", "Reg Hours"=>"5", "OT Hours"=>"10"}}
    
    转换为JSON

    基于此,您可以将哈希转换为json

    require 'json'
    employee.to_json
    

    我认为一般的做法是:

  • 为键为employee的每个表创建哈希
  • 将两个表的结果合并在一起
  • 转换为JSON
  • 为键为员工的每个表创建一个哈希值

    这部分可以在Watir或Nokogiri中完成。只有在Watir由于表太大而导致性能不佳时,使用Nokogiri才有意义

    瓦蒂尔:

    #I assume you would have a better way to identify the tables than by index
    hours_table = browser.table(:index, 0)
    wage_table = browser.table(:index, 1)
    
    #Turn the tables into a hash
    employee_hours = {}
    hours_table.trs.drop(1).each do |tr| 
        tds = tr.tds
        employee_hours[ tds[0].text ] = {"Reg Hours" => tds[1].text, "OT Hours" => tds[2].text}     
    end
    #=> {"Employee 1"=>{"Reg Hours"=>"10", "OT Hours"=>"20"}, "Employee 2"=>{"Reg Hours"=>"5", "OT Hours"=>"10"}}
    
    employee_wage = {}
    wage_table.trs.drop(1).each do |tr| 
        tds = tr.tds
        employee_wage[ tds[0].text ] = {"Revenue" => tds[1].text}   
    end
    #=> {"Employee 2"=>{"Revenue"=>"$10"}, "Employee 1"=>{"Revenue"=>"$50"}}
    
    诺科吉里:

    page = Nokogiri::HTML.parse(browser.html)
    
    hours_table = page.search('table')[0]
    wage_table = page.search('table')[1]
    
    employee_hours = {}
    hours_table.search('tr').drop(1).each do |tr| 
        tds = tr.search('td')
        employee_hours[ tds[0].text ] = {"Reg Hours" => tds[1].text, "OT Hours" => tds[2].text}     
    end
    #=> {"Employee 1"=>{"Reg Hours"=>"10", "OT Hours"=>"20"}, "Employee 2"=>{"Reg Hours"=>"5", "OT Hours"=>"10"}}
    
    employee_wage = {}
    wage_table.search('tr').drop(1).each do |tr| 
        tds = tr.search('td')
        employee_wage[ tds[0].text ] = {"Revenue" => tds[1].text}   
    end
    #=> {"Employee 2"=>{"Revenue"=>"$10"}, "Employee 1"=>{"Revenue"=>"$50"}}
    
    将两个表的结果合并在一起

    您希望将这两个哈希合并在一起,以便对于特定员工,哈希将包括他们的工作时间和收入

    employee = employee_hours.merge(employee_wage){ |key, old, new| new.merge(old) }
    #=> {"Employee 1"=>{"Revenue"=>"$50", "Reg Hours"=>"10", "OT Hours"=>"20"}, "Employee 2"=>{"Revenue"=>"$10", "Reg Hours"=>"5", "OT Hours"=>"10"}}
    
    转换为JSON

    基于此,您可以将哈希转换为json

    require 'json'
    employee.to_json
    


    您可以修改HTML以包含表元素的类吗?具体来说,标记可以有一个“employee”类,每个标记可以有一个类来表示它是什么(例如“name”、“revenue”等)这将帮助您匹配员工姓名,然后在另一个HTML文档中找到它,然后从这两个文档中构建JSON,或者在构建对象之前将它们合并在一起。HTML不是我的。获取xpath节点不是问题……我想我更多地停留在Ruby部分。我不确定如何迭代行并合并数据在这两个表之间。你想使用Nokogiri而不是Watir有什么原因吗?Cheezy/Jeff Morgan在页面对象中有一种从表中获取信息的方法:@JustinKo,Watir能做我需要做的吗?我在文档中找不到任何东西。你能修改HTML以包含表元素的类吗?特别是,标记可以有一个“employee”类和每个标记可以有一个类来表示它是什么(例如“名称”、“收入”等)这将帮助您匹配员工姓名,然后在另一个HTML文档中找到它,然后从这两个文档中构建JSON,或者在构建对象之前将它们合并在一起。HTML不是我的。获取xpath节点不是问题……我想我更多地停留在Ruby部分。我不确定如何迭代行并合并数据在这两个表之间。你为什么要使用Nokogiri而不是Watir?Cheezy/Jeff Morgan在页面对象中有一种从表中获取信息的方法:@JustinKo,Watir可以做我需要做的事情吗?我在文档中找不到任何东西。谢谢你的回复。我做了以下更改:hours_table=browser.tr(:xpath,//*[@id=“tblReportItems”]/tbody/tr[1]”),因为表ID现在似乎已消失。获取“未定义的方法哈希”错误不过,现在,从water webdriver开始,
    hash
    是为表而不是trs定义的。换句话说,您需要确保
    hours\u table
    仍然是一个表。根据建议的更改,您应该能够执行
    hours\u table=browser.table(:id=>tblReportItems'))
    。我明白了……但该表ID用于一个包罗万象的表。我需要的表在该表中(没有ID)。尝试您的nokogiri示例,我得到一个“text”的未定义方法错误。您是否更改了
    hours\u table
    wage\u table
    以指向正确的表?这两个解决方案都硬编码到页面上的第一个/第二个表中。您需要更新它们以处理特定的表(因为我不知道你的页面的html是什么样子)。我知道了;我需要的表分别是第五个和第六个。但是我仍然收到“text”的“no method”错误。谢谢你的回复。我做了以下更改:hours_table=browser.tr(:xpath,“/*[@id=“tblReportItems”]/tbody/tr[1])因为表ID现在似乎已消失。获取“未定义的方法'哈希'错误”不过,现在,从water webdriver开始,
    hash
    是为表而不是trs定义的。换句话说,您需要确保
    hours\u table
    仍然是一个表。根据建议的更改,您应该能够执行
    hours\u table=browser.table(:id=>tblReportItems'))
    。我明白了……但该表ID用于一个包罗万象的表。我需要的表在该表中(没有ID)。尝试您的nokogiri示例,我得到一个“text”的未定义方法错误。您是否更改了
    hours\u table
    wage\u table
    以指向正确的表?这两个解决方案都硬编码到页面上的第一个/第二个表中。您需要更新它们以处理特定的表(因为我不知道你的页面的html是什么样子的)。我知道了;我需要的表分别是第五个和第六个。不过,我仍然得到了“text”的“no method”错误。