首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Scrapy/Xpath对足球(足球)评论中的ESPN进行抓取

使用Scrapy/Xpath对足球(足球)评论中的ESPN进行抓取
EN

Code Review用户
提问于 2013-11-21 13:05:43
回答 2查看 1K关注 0票数 3

这个班从ESPN足球网站上输入一个游戏id。然后,代码必须抓取评论,处理它,并获取播放器的名称/ids,并创建一个小字典。

当在基本示例中显示时,我理解OOP的前提,但我无法在实际的程序/应用程序中使用它。我在这里试过了,但对我来说,它似乎并没有取得什么额外的成就(所以我肯定做错了)。

最后,我得到了一个列表,其中包含了每个关键事件(角、镜头等)和一本玩家字典,所以它起作用了。但是它看起来太不雅致了,我很喜欢一些改进它的技巧(不管它们多么的小/专注)。

代码语言:javascript
复制
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
EN

回答 2

Code Review用户

发布于 2013-11-21 17:11:21

  • 没有docstring,所以类的用户会想知道哪些方法可以调用。实际上,在研究了代码之后,看起来所有的方法都是由__init__按特定顺序调用的。让我怀疑这是否应该是一门课。
  • 您设置了许多实例属性,甚至是一个self.dummy,但是在设置它们的方法之外使用的很少。它们中的大多数应该是局部变量。再说一遍,我想你不需要一个类--所有的方法都可以是简单的函数,只需要一个或两个参数。
  • 这个类的目的似乎是初始化六个列表,例如。self.corners。因此,要了解游戏的概况,必须访问六个变量。最好使用一个可以轻松循环和查询的单一数据结构。也许像"corners"这样的字典适合您,但我认为最有用的方法是将事件保存在一个按时间顺序排列的列表中,并提供一个函数来按事件类型筛选该列表。
票数 5
EN

Code Review用户

发布于 2013-11-22 13:26:40

我在遵循这段代码时遇到了困难,所以我将重点关注可维护性。以下是一些您可以考虑更改的内容:

  • 一些成员目前在__init__中初始化,有些成员仅在其他方法中初始化。定义类的不变量通常是很好的,这些不变量在所有可观察的时间都将保持为真。因为__init__调用所有对外部用户来说仍然是正确的东西,但这会使您更难记住game's方法中已经准备好的内容。
  • 一些成员响应Janne Karila的要求,在没有其他任何东西可以看到他们的地方被利用。应该用本地人代替。也许解决这个问题会消除前一颗子弹的大部分奇怪情况。
  • findAction中有一个特例,用于调用它的许多参数之一。我发现findAction很难跟上。但我也不喜欢它如何通过引用和附加列表。通常情况下,返回一个值要更多的是pythonic。如果findAction创建并返回了一个列表,那么调用者可能是self.corners = self.findAction('^Corner')。这甚至会清除一些__init__
  • 有许多神奇的值与代码的其余部分混合在一起。有时候,将它们提取到一个位置并给它们一个有意义的名称是很好的。例如,URL格式字符串,或XPath字符串,甚至regex模式字符串。由于这些是不可变的值,我会考虑将这些值放在类中:类游戏: COMMS_URL_FMT = 'http://...%s...‘COMMENT_XPATH =“//div/.”def __init__(self,game_id):self.data_text = urllib2.urlopen(self.COMMS_URL_FMT % game_id).read()
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/35830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档