Skip to content

Commit

Permalink
Merge pull request #4 from toddrob99/develop
Browse files Browse the repository at this point in the history
###v0.0.7
* Added MLB copyright notice to README
* Added ability to call schedule() for specific game_id(s) (comma separated string)
* Added current inning to summary for schedule() when game is in progress, and status will now always be included
* Added ability to get standings for a given division, and to exclude wildcard standings
  • Loading branch information
toddrob99 authored May 4, 2019
2 parents a5c9b61 + ec3c8a3 commit cbc29f8
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 35 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Python wrapper for MLB Stats API

Created by Todd Roberts

https://pypi.org/project/MLB-StatsAPI/

https://github.com/toddrob99/MLB-StatsAPI

Documentation: https://toddrob99.github.io/MLB-StatsAPI/
Expand All @@ -25,7 +27,7 @@ If you install manually, be sure to also install requests.

* `statsapi.lookup_player()` - get a list of player data based on first, last, or full name, jersey number, current team Id, position, etc.

* `statsapi.lookup_team()` - get a lsit of teams info based on the team name, city, abbreviation, or file code
* `statsapi.lookup_team()` - get a list of teams' info based on the team name, city, abbreviation, or file code

* `statsapi.schedule()` - retrieve a list of games on a given date/range and/or team/opponent

Expand Down Expand Up @@ -145,3 +147,7 @@ print( statsapi.player_stats(next(x['id'] for x in statsapi.get('sports_players'
```
print( statsapi.game_scoring_plays(567074) )
```

## Copyright Notice

This API wrapper interfaces with MLB's Stats API. Use of MLB data is subject to the notice posted at http://gdx.mlb.com/components/copyright.txt.
84 changes: 54 additions & 30 deletions statsapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
https://pypi.org/project/MLB-StatsAPI/
https://github.com/toddrob99/MLB-StatsAPI
Documentation: https://toddrob99.github.io/MLB-StatsAPI/
"""
import sys
if sys.version_info.major < 3:
Expand All @@ -31,18 +33,20 @@
import requests
from datetime import datetime

def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sportId=1):
def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sportId=1, game_id=None):
"""Get list of games for a given date/range and/or team/opponent.
Include a game_id to get data for that game.
Output will be a list containing a dict for each game. Fields in the dict:
'game_id': unique MLB game id (primary key, or gamePk)
'game_datetime': date and timestamp in UTC (be careful if you truncate the time--the date may be the next day for a late game)
'game_date': date of game (YYYY-MM-DD)
'game_type': Preseason, Regular season, Postseason, etc. Look up possible values using the meta endpoint with type=gameTypes
'status': Scheduled, Warmup, In Progress, Final, etc. Look up possible values using the meta endpoint with type=gameStatus
'away': team name for the away team (e.g. Philadelphia Phillies)
'home': team name for the home team (e.g. Philadelphia Phillies)
'away_name': team name for the away team (e.g. Philadelphia Phillies)
'home_name': team name for the home team (e.g. Philadelphia Phillies)
'away_id': team id for the away team, e.g. 143. Use this to look up other info about a team using the team endpoint with teamId=143
'home_id': team id for the home team, e.g. 143. Use this to look up other info about a team using the team endpoint with teamId=143
'doubleheader': indicates if the game is part of a straight doubleheader (Y), a split doubleheader (S), or not part of a doubleheader
Expand All @@ -54,8 +58,14 @@ def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sp
'winning_pitcher': full name of the winning pitcher, if the game is final and has a winner (not postponed/tied)
'losing_pitcher': full name of the losing pitcher, if the game is final and has a winner (not postponed/tied)
'save_pitcher': full name of the pitcher credited with a save, if the game is final and has a winner (not postponed/tied)
'summary': if the game is final, the summary will include "<Date> - <Away Team Name> (<Away Score>) @ <Home Team Name> (<Home Score>)"
if the game is not final, the summary will include "<Date> - <Away Team Name> @ <Home Team Name> (<Game Status>)"
'home_probable_pitcher': full name of the probable pitcher for the home team, if available
'away_probable_pitcher': full name of the probable pitcher for the away team, if available
'home_pitcher_note': pitching report for the home team probable pitcher, if available
'away_pitcher_note': pitching report for the away team probable pitcher, if available
'current_inning': current inning (applies best to in-progress games)
'inning_state': state of current inning: top, middle, bottom, end (applies best to in-progress games)
'summary': if the game is final or in progress, the summary will include "<Date> - <Away Team Name> (<Away Score>) @ <Home Team Name> (<Home Score>) (<Game Status>)"
if the game has not started yet, the summary will include "<Date> - <Away Team Name> @ <Home Team Name> (<Game Status>)"
Example use:
Expand All @@ -70,10 +80,10 @@ def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sp
Output:
2018-07-09 - Philadelphia Phillies (3) @ New York Mets (4)
2018-07-09 - Philadelphia Phillies (3) @ New York Mets (1)
2018-07-10 - Philadelphia Phillies (7) @ New York Mets (3)
2018-07-11 - Philadelphia Phillies (0) @ New York Mets (3)
2018-07-09 - Philadelphia Phillies (3) @ New York Mets (4) (Final)
2018-07-09 - Philadelphia Phillies (3) @ New York Mets (1) (Final)
2018-07-10 - Philadelphia Phillies (7) @ New York Mets (3) (Final)
2018-07-11 - Philadelphia Phillies (0) @ New York Mets (3) (Final)
Print a list of decisions for those games:
Expand Down Expand Up @@ -105,7 +115,9 @@ def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sp
if opponent != '':
params.update({'opponentId':str(opponent)})

params.update({'sportId':str(sportId), 'hydrate':'decisions'})
if game_id: params.update({'gamePks':game_id})

params.update({'sportId':str(sportId), 'hydrate':'decisions,probablePitcher(note),linescore'})

r = get('schedule',params)

Expand All @@ -121,22 +133,24 @@ def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sp
'game_date': date['date'],
'game_type': game['gameType'],
'status': game['status']['detailedState'],
'away': game['teams']['away']['team']['name'],
'home': game['teams']['home']['team']['name'],
'away_name': game['teams']['away']['team']['name'],
'home_name': game['teams']['home']['team']['name'],
'away_id': game['teams']['away']['team']['id'],
'home_id': game['teams']['home']['team']['id'],
'doubleheader': game['doubleHeader'],
'game_num': game['gameNumber']
'game_num': game['gameNumber'],
'home_probable_pitcher': game['teams']['home'].get('probablePitcher',{}).get('fullName',''),
'away_probable_pitcher': game['teams']['away'].get('probablePitcher',{}).get('fullName',''),
'home_pitcher_note': game['teams']['home'].get('probablePitcher').get('note',''),
'away_pitcher_note': game['teams']['away'].get('probablePitcher').get('note',''),
'away_score': game['teams']['away'].get('score','0'),
'home_score': game['teams']['home'].get('score','0'),
'current_inning': game['linescore'].get('currentInning',''),
'inning_state': game['linescore'].get('inningState','')
}
if game_info['status'] == 'Final':
game_info.update({
'away_score': game['teams']['away']['score'],
'home_score': game['teams']['home']['score']
})
if game_info['status'] in ['Final','Game Over']:
if game.get('isTie'):
game_info.update({
'away_score': game['teams']['away']['score'],
'home_score': game['teams']['home']['score'],
'winning_team': 'Tie',
'losing_Team': 'Tie'
})
Expand All @@ -148,8 +162,12 @@ def schedule(date=None, start_date=None, end_date=None, team='', opponent='', sp
'losing_pitcher': game['decisions'].get('loser',{}).get('fullName',''),
'save_pitcher': game['decisions'].get('save',{}).get('fullName')
})
summary = date['date'] + ' - ' + game['teams']['away']['team']['name'] + ' (' + str(game['teams']['away']['score']) + ') @ ' + game['teams']['home']['team']['name'] + ' (' + str(game['teams']['home']['score']) + ')'
summary = date['date'] + ' - ' + game['teams']['away']['team']['name'] + ' (' + str(game['teams']['away']['score']) + ') @ ' + game['teams']['home']['team']['name'] + ' (' + str(game['teams']['home']['score']) + ') (' + game['status']['detailedState'] + ')'
game_info.update({'summary': summary})
elif game_info['status'] == 'In Progress':
game_info.update({
'summary': date['date'] + ' - ' + game['teams']['away']['team']['name'] + ' (' + str(game['teams']['away']['score']) + ') @ ' + game['teams']['home']['team']['name'] + ' (' + str(game['teams']['home']['score']) + ') (' + game['linescore']['inningState'] + ' of the ' + game['linescore']['currentInningOrdinal'] + ')'
})
else:
summary = date['date'] + ' - ' + game['teams']['away']['team']['name'] + ' @ ' + game['teams']['home']['team']['name'] + ' (' + game['status']['detailedState'] + ')'
game_info.update({'summary': summary})
Expand Down Expand Up @@ -1108,9 +1126,12 @@ def league_leaders(leaderCategories,season=None,limit=10,statGroup=None,leagueId

return leaders

def standings(leagueId=None,season=None,standingsTypes=None,date=None):
"""Get formatted standings for a given league and season.
Will include division and wildcard standings
def standings(leagueId='103,104',division='all',include_wildcard=True,season=None,standingsTypes=None,date=None):
"""Get formatted standings for a given league/division and season.
Using both leagueId and divisionId is fine, as long as the division belongs to the specified league
Return value will be a formatted table including division and wildcard standings, unless include_wildcard=False
Format for date = 'MM/DD/YYYY', e.g. '04/24/2019'
Expand Down Expand Up @@ -1148,7 +1169,6 @@ def standings(leagueId=None,season=None,standingsTypes=None,date=None):
5 Washington Nationals 59 101 31.5 E 13 29.5 E
"""
if not leagueId: leagueId = '103,104'
params = {'leagueId':leagueId}
if date: params.update({'date':date})
if not season:
Expand All @@ -1158,7 +1178,6 @@ def standings(leagueId=None,season=None,standingsTypes=None,date=None):
season = datetime.now().year
if not standingsTypes: standingsTypes = 'regularSeason'
params.update({'season':season,'standingsTypes':standingsTypes})
if leagueId: params.update({'leagueId':leagueId})
params.update({'hydrate':'team(division)','fields':'records,standingsType,teamRecords,team,name,division,id,nameShort,abbreviation,divisionRank,gamesBack,wildCardRank,wildCardGamesBack,wildCardEliminationNumber,divisionGamesBack,clinched,eliminationNumber,winningPercentage,type,wins,losses'})

r = get('standings',params)
Expand All @@ -1167,7 +1186,7 @@ def standings(leagueId=None,season=None,standingsTypes=None,date=None):
divisions = {}

for y in r['records']:
for x in y['teamRecords']:
for x in (x for x in y['teamRecords'] if division.lower()=='all' or division.lower()==x['team']['division']['abbreviation'].lower()):
if x['team']['division']['id'] not in divisions.keys():
divisions.update({x['team']['division']['id']:{'div_name':x['team']['division']['name'],'teams':[]}})
team = {
Expand All @@ -1185,9 +1204,14 @@ def standings(leagueId=None,season=None,standingsTypes=None,date=None):

for div_id,div in divisions.items():
standings += div['div_name'] + '\n'
standings += '{:^4} {:<21} {:^3} {:^3} {:^4} {:^4} {:^7} {:^5} {:^4}\n'.format(*['Rank','Team','W','L','GB','(E#)','WC Rank','WC GB','(E#)'])
for t in div['teams']:
standings += '{div_rank:^4} {name:<21} {w:^3} {l:^3} {gb:^4} {elim_num:^4} {wc_rank:^7} {wc_gb:^5} {wc_elim_num:^4}\n'.format(**t)
if include_wildcard:
standings += '{:^4} {:<21} {:^3} {:^3} {:^4} {:^4} {:^7} {:^5} {:^4}\n'.format(*['Rank','Team','W','L','GB','(E#)','WC Rank','WC GB','(E#)'])
for t in div['teams']:
standings += '{div_rank:^4} {name:<21} {w:^3} {l:^3} {gb:^4} {elim_num:^4} {wc_rank:^7} {wc_gb:^5} {wc_elim_num:^4}\n'.format(**t)
else:
standings += '{:^4} {:<21} {:^3} {:^3} {:^4} {:^4}\n'.format(*['Rank','Team','W','L','GB','(E#)'])
for t in div['teams']:
standings += '{div_rank:^4} {name:<21} {w:^3} {l:^3} {gb:^4} {elim_num:^4}\n'.format(**t)
standings += '\n'

return standings
Expand Down
3 changes: 2 additions & 1 deletion statsapi/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@
}
},
'query_params': ['timecode','fields'],
'required_params': [[]]
'required_params': [[]],
'note': 'If you only want the current win probability for each team, try the game_contextMetrics endpoint instad.'
},
'game_boxscore': {
'url': BASE_URL + '{ver}/game/{gamePk}/boxscore',
Expand Down
2 changes: 0 additions & 2 deletions statsapi/test.py

This file was deleted.

2 changes: 1 addition & 1 deletion statsapi/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/env python

VERSION = '0.0.6'
VERSION = '0.0.7'

0 comments on commit cbc29f8

Please sign in to comment.