【问题标题】:Using Ruby and Mechanize to make new Olympic medals count使用 Ruby 和 Mechanize 计算新的奥运奖牌
【发布时间】:2012-08-02 00:06:00
【问题描述】:

我想重新设计2012年伦敦奥运会的奖牌,以更好地体现奖牌的价值。目前仅按金牌排序。我想按点重新列出它,所以金=4,银=2,青铜=1,以制作一个新的更合理的名单。我可能想记住以前的排名,然后添加一个新的排名列。

我想尝试机械化以从站点获取原始数据,然后将数据解析为行和列,应用新计数,然后重新制作列表。

来自http://www.london2012.com/medals/medal-count/ 的来源,每个国家/地区都有一个带有这样奖牌的区块:

<span class="countryName">Canada</span></a></div></div></td><td class="gold c">0</td><td class="silver c">2</td><td class="bronze c">5</td>

如果我使用 agent.get('http://www.london2012.com/medals/medal-count') 它会显示整个列表。如何解析特定的 span 和 table 数据?

我还需要记住排名,然后在创建新页面时将新排名放在它旁边。

任何有关机械化解析和记忆数据的技巧都会非常有帮助。更重要的是你在做这样的事情时的思考过程,我很感激能帮助我开始。这不一定是代码答案

谢谢

【问题讨论】:

    标签: ruby mechanize


    【解决方案1】:

    您可能会发现此 Medals API 很有用(假设您的问题并非专门针对 Mechanize)

    http://apify.heroku.com/resources/5014626da8cdbb0002000006

    它使用 Nokogiri 来解析网站,输出为 JSON:

    http://apify.heroku.com/api/olympics2012_medals.json

    【讨论】:

      【解决方案2】:

      首先识别表。在 chrome 中加载页面并右键单击表格上的任意位置。去检查元素。向上层级,直到你在桌子上。现在选择它,你会看到它看起来像这样:

      <table class="or-tbl overall_medals sortable" summary="Schedule">
      

      overall_medals 类看起来是独一无二的,所以它是一个很好用的类。现在启动 irb 并执行以下操作:

      require 'mechanize'
      agent = Mechanize.new
      page = agent.get 'http://www.london2012.com/medals/medal-count/'
      

      仔细检查表是否唯一:

      page.search('table.overall_medals').size 
      #=> 1 (good, it is)
      

      您可以使用以下方法将表中的所有数据放入数组中:

      page.search('table.overall_medals tr').map{|tr| tr.search('td').map(&:text)}
      

      注意前 2 行是空的,让我们通过使用范围来摆脱它们:

      data = page.search('table.overall_medals tr')[2..-1].map{|tr| tr.search('td').map(&:text)}
      

      第二行并不是真正的空,它有列名(在 th 中而不是 td 中)。您可以通过以下方式获得:

      columns = page.search('table.overall_medals tr[2] th').map{|th| th.text.strip}
      

      您可以使用以下方法将它们放入哈希中:

      rows = data.map{|row| Hash[columns.zip row]}
      

      现在你可以做

      rows[0]['Country']
      #=> "United States of America"
      

      甚至是一个大哈希:

      countries = rows.map{|row| {row['Country'] => row}}.reduce &:merge
      

      现在:

      countries['France']['Gold']
      #=> "8"
      

      【讨论】:

      • 哇.. &:text 和 &:merge 项是做什么的?顶部的第 4 个代码块是映射搜索图,所以我想知道您是否可以用文字表达它在做什么。接下来从 2 到 -1,我认为这是开始,所以我还可以。
      • 行 = data.map{|row| Hash[columns.zip row]}你能解释一下这里的zip吗?
      • map(&:text) 是 map{|x| 的快捷方式x.text},与 &:merge 相同。 columns.zip(row) 会将列与 row 对齐,如下所示: [[column[0], row[0]], [column[1], row[1]], etc] 因此可以轻松放入一个哈希
      • 啊哈!非常感谢您抽出宝贵的时间。周末愉快;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      • 2010-11-15
      • 1970-01-01
      相关资源
      最近更新 更多