The NHL has an interesting API that can access a wide range of information. It isn’t officially documented but I found some decent informal documentation.
For fun, I wrote a Python program to get the live feed for the games going on today. It’s nothing special but was an interesting diversion. The biggest challenge is working with the live feed when I want to watch the game.
The code is below:
from datetime import datetime
import jmespath
import json
import requests
from requests.exceptions import HTTPError
import sys
import time
BASE_URL = 'https://statsapi.web.nhl.com'
def main():
# get today's date in yyyy-mm-dd format
today = datetime.today().strftime('%Y-%m-%d')
active_games = get_active_games(today)
if len(active_games) == 0:
print("No active games")
sys.exit()
# loop through and get the live information for each game
while True:
for game_url in active_games:
res = get_url(game_url)
# get the teams
away = jmespath.search("gameData.teams.away.name", res)
home = jmespath.search("gameData.teams.home.name", res)
# get the game status
status = jmespath.search("gameData.status.detailedState", res)
# remove the games that are postponed or final
if status == "Postponed" or status == "Final":
active_games.remove(game_url)
else:
# get the last play
current_play = jmespath.search("liveData.plays.allPlays[-1].result.event", res)
print(f"{away} @ {home}: {current_play}")
# sleep after each round
time.sleep(10)
# stop the loop if there are no more games left
if len(active_games) == 0:
print("All active games complete")
sys.exit()
def get_active_games(date):
""" get_active_games returns array of games for date in yyyy-mm-dd format """
calendar_url = BASE_URL + '/api/v1/schedule?date=' + date
res = get_url(calendar_url)
current_games = jmespath.search("dates[0].games[].link", res)
# check the live feed for the status of the games
active_games = []
for link in current_games:
game_url = BASE_URL + link
res = get_url(game_url)
# get the game status
status = jmespath.search("gameData.status.detailedState", res)
away = jmespath.search("gameData.teams.away.name", res)
home = jmespath.search("gameData.teams.home.name", res)
# remove the games that are postponed or final
if status == "Postponed":
print(f"{away} at {home} postponed")
elif status == "Final":
away_goals = jmespath.search("liveData.linescore.teams.away.goals", res)
home_goals = jmespath.search("liveData.linescore.teams.home.goals", res)
print(f"Final {away}:{away_goals} {home}:{home_goals}")
else:
active_games.append(game_url)
return active_games
def get_url(url):
""" get_url returns json string for a given url or prints an error """
try:
response = requests.get(url)
response.raise_for_status()
except HTTPError as http_err:
print(f'HTTP error: {http_error}')
except Exception as err:
print('Error: {err}')
else:
return response.json()
if __name__ == "__main__":
main()