这个班从ESPN足球网站上输入一个游戏id。然后,代码必须抓取评论,处理它,并获取播放器的名称/ids,并创建一个小字典。
当在基本示例中显示时,我理解OOP的前提,但我无法在实际的程序/应用程序中使用它。我在这里试过了,但对我来说,它似乎并没有取得什么额外的成就(所以我肯定做错了)。
最后,我得到了一个列表,其中包含了每个关键事件(角、镜头等)和一本玩家字典,所以它起作用了。但是它看起来太不雅致了,我很喜欢一些改进它的技巧(不管它们多么的小/专注)。
import urllib2
from scrapy.selector import HtmlXPathSelector
import re
import codecs
import timeit
start = timeit.default_timer()
class game:
def __init__(self,game_id):
self.game_id = game_id
self.comms_url = 'http://espnfc.com/uk/en/gamecast/%d/gamecast.html?soccernet=true&cc=5739' % self.game_id
self.data_text = urllib2.urlopen(self.comms_url).read()
self.corners = []
self.shots = []
self.fouls = []
self.shots_on_target = []
self.offsides = []
self.goals = []
self.extractCommentaries()
self.extractPlayers()
self.extractTeams()
self.findAction('^Corner', self.corners)
self.findAction('^Foul by', self.fouls)
self.findAction('^Attempt', self.shots)
self.findAction('^Attempt saved', self.shots_on_target)
self.findAction('^Offside', self.offsides)
self.findAction('^Goal!', self.goals)
def extractCommentaries(self):
self.hxs = HtmlXPathSelector(text=self.data_text)
self.match_comments = self.hxs.select("//div[@id='convo-window']/ul[@id='convo-list']/li/div[@class='comment']/p/text()")
self.match_timestamps = self.hxs.select("//div[@id='convo-window']/ul[@id='convo-list']/li/div[@class='timestamp']/p/text()")
self.events = zip(self.match_timestamps.extract(), self.match_comments.extract())
self.cleanclean = []
for time,event in self.events:
time = re.search('\d+', time)
if time:
time = time.group()
time = int(time)
self.cleanclean.append((time,event))
self.dumdum = range(len(self.events))
self.clean_events = {}
for key, event in enumerate(self.cleanclean):
self.clean_events[key] = event
def extractPlayers(self):
self.player_names = self.hxs.select("//table[@class='stat-table']/tbody//a/text()")
self.player_urls = self.hxs.select("//table[@class='stat-table']/tbody//a/@href")
self.player_ids = []
for url in self.player_urls.extract():
digit = []
for s in url:
if s.isdigit():
digit.append(s)
self.placeholder = ''.join(digit)
self.placeholder = int(self.placeholder)
self.player_ids.append(self.placeholder)
self.players = dict(zip(self.player_ids, self.player_names.extract()))
def extractTeams(self):
self.dummy = ['home','away']
self.zero = [0,0]
self.team_names = self.hxs.select("//li[@class='country']/h2/text()")
self.teams = dict(zip(self.dummy,self.team_names.extract()))
def findAction(self, keyword, storage):
for key, value in self.clean_events.iteritems():
action = re.search(keyword, value[1])
if action:
for ha, team in self.teams.iteritems():
if keyword == '^Goal!':
split_up_action = value[1].split('.')
found = re.search(team, split_up_action[1])
else:
found = re.search(team, value[1])
if found:
temp_holder = [value[0], team, self.game_id]
storage.append(temp_holder)
a = game()
stop = timeit.default_timer()
print stop - start发布于 2013-11-21 17:11:21
__init__按特定顺序调用的。让我怀疑这是否应该是一门课。self.dummy,但是在设置它们的方法之外使用的很少。它们中的大多数应该是局部变量。再说一遍,我想你不需要一个类--所有的方法都可以是简单的函数,只需要一个或两个参数。self.corners。因此,要了解游戏的概况,必须访问六个变量。最好使用一个可以轻松循环和查询的单一数据结构。也许像"corners"这样的字典适合您,但我认为最有用的方法是将事件保存在一个按时间顺序排列的列表中,并提供一个函数来按事件类型筛选该列表。发布于 2013-11-22 13:26:40
我在遵循这段代码时遇到了困难,所以我将重点关注可维护性。以下是一些您可以考虑更改的内容:
__init__中初始化,有些成员仅在其他方法中初始化。定义类的不变量通常是很好的,这些不变量在所有可观察的时间都将保持为真。因为__init__调用所有对外部用户来说仍然是正确的东西,但这会使您更难记住game's方法中已经准备好的内容。findAction中有一个特例,用于调用它的许多参数之一。我发现findAction很难跟上。但我也不喜欢它如何通过引用和附加列表。通常情况下,返回一个值要更多的是pythonic。如果findAction创建并返回了一个列表,那么调用者可能是self.corners = self.findAction('^Corner')。这甚至会清除一些__init__。https://codereview.stackexchange.com/questions/35830
复制相似问题