我最近获得了从雅虎NHL页面获得分数的帮助,该页面将以相应的方式打印出团队及其上述分数。这是我的代码:
from bs4 import BeautifulSoup
from urllib.request import urlopen
url = urlopen("http://sports.yahoo.com/nhl/scoreboard?d=2013-01-19")
content = url.read()
soup = BeautifulSoup(content)
def yahooscores():
results = {}
for table in soup.find_all('table', class_='scores'):
for row in table.find_all('tr'):
scores = []
name = None
for cell in row.find_all('td', class_='yspscores'):
link = cell.find('a')
if link:
name = link.text
elif cell.text.isdigit():
scores.append(cell.text)
if name is not None:
results[name] = scores
for name, scores in results.items():
print ('%s: %s' % (name, ', '.join(scores)) + '.')
yahooscores()
现在,首先:我在函数中关联这些东西,因为我将不得不经常更改网址以获取1月份每一天的所有值。
这里的问题是,虽然我可以打印分数和团队文本,但我正在努力实现这一目标:
Ottawa: 1, 1, 2.
Winnipeg: 1, 0, 0.
Pittsburgh: 2, 0, 1
Philadelphia: 0, 1, 0.
看,我的代码不这样做。我正在试图让这种情况发生,但令这个过程变得复杂的是,这些表格都属于同一类“分数”,看起来,我找不到它们之间的任何不同。
简而言之,将团队正确地相互关联,并在组织之间留出空间。
答案 0 :(得分:1)
问题是,您将每个团队的结果都放入dict
,但dict
中没有订单,因此您无法跟踪哪个分数来自页面上的哪个表(即哪场比赛)。
要解决这个问题,您可以直接打印结果而不是存储它们,并在外部for循环中添加额外的换行符:
def yahooscores():
results = {}
for table in soup.find_all('table', class_='scores'):
for row in table.find_all('tr'):
scores = []
name = None
for cell in row.find_all('td', class_='yspscores'):
link = cell.find('a')
if link:
name = link.text
elif cell.text.isdigit():
scores.append(cell.text)
if name is not None:
print ('%s: %s' % (name, ', '.join(scores)) + '.')
print ""
yahooscores()
或者,如果您想存储乐谱并在以后显示它们,您也可以存储每个游戏的团队并使用它们对结果进行分组:
def yahooscores():
results = {}
games = []
for table in soup.find_all('table', class_='scores'):
teams = []
for row in table.find_all('tr'):
scores = []
name = None
for cell in row.find_all('td', class_='yspscores'):
link = cell.find('a')
if link:
name = link.text
elif cell.text.isdigit():
scores.append(cell.text)
if name is not None:
results[name] = scores
teams.append(name)
games.append(teams)
for teams in games:
for name in teams:
scores = results[name]
print ('%s: %s' % (name, ', '.join(scores)) + '.')
print ""
yahooscores()
答案 1 :(得分:0)
问题在于你将表视为一个单独的团队列表,而不是作为一个分数列表,每个分数都包含两个团队。
解决这个问题的干净方法是改变解析页面的方式,以便循环游戏,然后,对于每个游戏,存储类似于一对名称和分数的内容。
但也有一个快速而又肮脏的解决方案:如果你让团队保持秩序,你可以在事后配对。 dict
没有固有顺序,但OrderedDict
保留了插入顺序。因此,只需将results = {}
更改为results = collections.OrderedDict
。
(虽然你对这个词典做过的唯一事情是迭代它items()
,但我不确定你为什么想要一本字典。只需results = []
,替换{{1} }使用results[name] = scores
,然后迭代results.append((name, scores))
而不是results
。)
现在,如果你想成对地打印它们......好吧,你可以很容易地从任何迭代中成对迭代器。例如:
results.items()
或者,如果你不明白这意味着什么,像这样的hacky也可以正常工作:
def pairs(iterable):
return zip(*[iter(iterable)]*2)
for (name1, score1), (name2, score2) in pairs(results.items()):
print ('%s: %s' % (n1, ', '.join(s1)) + '.')
print ('%s: %s' % (n2, ', '.join(s2)) + '.')
print
......或:
pair_done = False
for name, scores in results.items():
print ('%s: %s' % (name, ', '.join(scores)) + '.')
if pair_done:
print
pair_done = not pair_done