1

我想改造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') 它会显示整个列表。如何解析特定的跨度和表数据?

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

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

谢谢

4

2 回答 2

2

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

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

general_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"
于 2012-08-04T02:20:42.423 回答
1

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

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

它使用 Nokogiri 来解析站点,并且输出以 JSON 格式提供:

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

于 2012-08-11T20:00:08.837 回答