def loadGamelogs(self, year=None): """ Loads gamelogs for the player for a given year Arguments: year : The season desired. Defaults to the current year if not specified """ if year is None: year = datetime.datetime.now().year if year not in self.logs: self.logs[year] = [] if 'primary_position' not in self: logger.error("no primary position attribute for " % self) return False url = Fetcher.MLB_PITCHER_URL if self['primary_position'] == 1 else Fetcher.MLB_BATTER_URL f = Fetcher(url, player_id=self.player_id, year=year) j = f.fetch() try: if self['primary_position'] == 1: parent = j['mlb_bio_pitching_last_10']['mlb_individual_pitching_game_log']['queryResults'] else: if 'mlb_individual_hitting_last_x_total' in j: parent = j['mlb_individual_hitting_last_x_total']['mlb_individual_hitting_game_log']['queryResults'] else: parent = j['mlb_bio_hitting_last_10']['mlb_individual_hitting_game_log']['queryResults'] except KeyError, e: logger.error('no key for gamelogs found in %s' % f.url) return False
def fetch(self, raw=False): """ Makes the HTTP request to the MLB.com server and handles the response """ req = requests.get(self.url) if self.url.find('xml') >= 0: req_type = 'XML' elif self.url.find('json') >= 0: req_type = 'JSON' else: req_type = 'HTML' logger.debug("fetching %s" % self.url) if req.status_code != requests.status_codes.codes.OK: logger.error("Status code {0} returned from {1}".format(req.status_code, self.url)) return {} if raw: return req.content if req_type == 'JSON': try: return parseJSON(req.json()) except Exception, e: # log the error and return an empty object logger.error("error parsing %s\n%s\n%s" % (self.url, e, req.content)) return {}
def execute(self, sql, values = None): """ Executes a query Arguments: sql - The query values - A list of values to be bound """ self._count = None try: self.cursor.execute(sql, values) self.db.commit() except (MySQLdb.Warning, MySQLdb.Error), e: logger.error('QUERY ERROR: %s\nQUERY: %s\nVALUES: %s\n\n' % (e, sql, ','.join([str(v) for v in values]))) pass
def execute(self, sql, values=None): """ Executes a query Arguments: sql - The query values - A list of values to be bound """ self._count = None cursor = self.db.cursor() try: cursor.execute(sql, values) self.db.commit() except (MySQLdb.Warning, MySQLdb.Error), e: logger.error('QUERY ERROR: %s\nQUERY: %s\nVALUES: %s\n\n' % (e, sql, ','.join([str(v) for v in values]))) pass
def load(self, load_yearlies=False, id=None): """ Calls MLB.com server and loads player information. If call fails, '_error' property is set. Arguments: id : The MLB.com player ID """ if id is None and self.player_id is not None: id = self.player_id self['player_id'] = self.player_id else: raise Exception('No player_id specified') f = Fetcher(Fetcher.MLB_PLAYER_URL, player_id=self.player_id) j = f.fetch() try: records = j['player_info']['queryResults']['totalSize'] except KeyError, e: msg = 'ERROR on %s: totalSize not returned for call' % f.url self._error = msg logger.error(msg) return False
class Fetcher: """ Responsible for all calls to MLB.com servers as well as parsing the responses """ # URL for the league MLB_LEAGUE_URL = "http://mlb.mlb.com/properties/mlb_properties.xml" # roster for a particular team MLB_ROSTER_URL = "http://mlb.mlb.com/lookup/json/named.roster_40.bam" \ "?team_id=%team_id%" # player detail MLB_PLAYER_URL = "http://mlb.com/lookup/json/named.player_info.bam" \ "?sport_code='mlb'&player_id='%player_id%'" # pitcher gamelogs MLB_PITCHER_URL = "http://mlb.com/lookup/json/named.mlb_bio_pitching_last_10.bam" \ "?results=100&game_type='R'&season=%year%&player_id=%player_id%" # pitcher career and season totals MLB_PITCHER_SUMMARY_URL = "http://mlb.com/lookup/json/named.mlb_bio_pitching_summary.bam" \ "?game_type='R'&sort_by='season_asc'&player_id=%player_id%" # batter gamelogs MLB_BATTER_URL = "http://mlb.com/lookup/json/named.mlb_bio_hitting_last_10.bam" \ "?results=165&game_type='R'&season=%year%&player_id=%player_id%" # batter career and season totals MLB_BATTER_SUMMARY_URL = "http://mlb.mlb.com/lookup/json/named.mlb_bio_hitting_summary.bam" \ "?game_type='R'&sort_by='season_asc'&player_id=%player_id%" # scheduling MLB_SCHEDULE_URL = "http://mlb.mlb.com/components/schedule/schedule_%date%.json" # transactions MLB_TRANSACTION_URL = "http://web.minorleaguebaseball.com/lookup/json/named.transaction_all.bam" \ "?league_id=104&start_date=%start%&end_date=%end%" # transactions archive - not yet used MLB_TRANSACTION_URL_ARCHIVE = "http://web.minorleaguebaseball.com/gen/stats/jsdata/2005/leagues/l113_200507_tra.js" # NOT YET USED MLB_STANDINGS_URL = "http://mlb.mlb.com/lookup/named.standings_all_league_repeater.bam" \ "?sit_code=%27h0%27&season=2005&league_id=103&league_id=104" def __init__(self, url, **kwargs): """ Constructor url : URL to fetch, one of the URLs defined in the Fetcher class kwargs : Any passed keyword is replaced into the URL with %key% format """ for key in kwargs.keys(): url = url.replace('%%%s%%' % key, str(kwargs[key])) # get rid of any unmatched %key% fields url = re.sub('%%.+?%%', '', url) self.url = url def fetch(self, returnRaw = False): """ Makes the HTTP request to the MLB.com server and handles the response """ req = urllib2.Request(self.url) if self.url.find('xml') >= 0: reqType = 'XML' elif self.url.find('json') >= 0: reqType = 'JSON' else: reqType = 'HTML' logger.debug("fetching %s" % self.url) try: res = urllib2.urlopen(req) content = res.read() except (urllib2.URLError, IOError), e: return {} if returnRaw: return content if reqType == 'JSON': # remove code comments that MLB puts in the response content = re.sub('\/\*.+?\*\/', '', content) try: obj = json.loads(content) return parseJSON(obj) except Exception, e: # log the error and return an empty object logger.error("error parsing %s\n%s\n%s" % (self.url, e, content)) return {}
f = Fetcher(Fetcher.MLB_PLAYER_URL, player_id=self.player_id) j = f.fetch() try: records = j['player_info']['queryResults']['totalSize'] except KeyError, e: msg = 'ERROR on %s: totalSize not returned for call' % f.url self._error = msg logger.error(msg) return False if records == 0: msg = 'ERROR on %s: totalSize is 0' % f.url self._error = msg logger.error(msg) return False try: records = j['player_info']['queryResults']['row'] except KeyError, e: self._error = 'ERROR on %s: key %s not found' % (f.url, e) logger.error('ERROR on %s: key %s not found\n%s' % (f.url, e, j)) return False if not isinstance(records, dict): msg = 'ERROR on %s: records should be a dict but got a %s' % ( f.url, type(records)) self._error = msg logger.error(msg) return False