Utilizing Yahoo's Fantasy Sports API to Import Fantasy Football League Data

My friends and I are part of a fantasy football league that was started in 2002. With over a decade and a half worth of history, our league is pretty intense. Unfortunately, it lacks a proper record-keeping system to keep track of all statistics. To go back and retrieve the data one would have to manually copy and paste everything, a time-consuming task. In this post, I illustrate how to connect to Yahoo’s Fantasy Sports API with oauth 2 authorization, make a request for league data, receive response object, parse the XML response object and finally write the data to a csv file.

Connecting to Yahoo’s Fantasy Sports API

To begin we first have to sign up at Yahoo’s Developer Network to receive a consumer key and consumer secret. Once you have the consumer key and consumer secret open up a text editor and type in the following:

{
"consumer_key": "paste_consumer_key_here",
"consumer_secret": "paste_my_consumer_secret_here"
}

After pasting the consumer key and consumer secret, save the file as oauth2.json and place it in the working directory.

Yahoo_oauth is a great python library package that supports OAuth authentication mechanism necessary to access many of Yahoo services. Once the yahoo_oauth package is downloaded via pip we can start the process of connecting to Yahoo’s Fantasy Sports API.

from yahoo_oauth import OAuth2
oauth = OAuth2(None, None, from_file='oauth2.json')
if not oauth.token_is_valid():
​ oauth.refresh_access_token()

With that we’re connected and have established an oauth2 authentication necessary to send requests.

Sending Request and Receiving Response Object

This lengthy documentation explains the parameters that needs to be provided when sending a request. Essentially the building blocks of the API are Collections and Resources. Resources are typically a reference to single entity such as a league, a team or a player. A Collection is simply a wrapper that contain multiple similar resources. A Resource is referred to by a Single Key, while collection will be referred to by Multiple Keys. Using multiple keys I can retrieve data for multiple leagues at once. After researching further and going through the documentation I was able to determine the league keys for our league for every year since 2002. They’re summarized below.

Year League_Key
2002 49.l.**
2003 79.l.**
2004 101.l.**
2005 124.l.**
2006 153.l.**
2007 175.l.**
2008 199.l.**
2009 222.l.**
2010 242.l.**
2011 257.l.**
2012 273.l.**
2013 314.l.**
2014 331.l.**
2015 348.l.**
2016 359.l.**
2017 371.l.**
url = "https://fantasysports.yahooapis.com/fantasy/v2/leagues;league_keys=
​ 79.l.******, 101.l.******, 124.l.******, 153.l.******,
​ 175.l.******, 199.l.******, 222.l.******, 242.l.******,
​ 257.l.******, 273.l.******, 314.l.******, 331.l.******,
​ 348.l.******, 359.l.******, 371.l.******/standings"
r = oauth.session.get(url)
r.status_code

A status code of 200 will indicate Success - The action was successfully received, understood, and accepted.

Parsing the XML response object and writing it to csv file

After a successful status code of 200 we receive a XML response object. To parse and modify the XML response object, I use ElementTree and re. Finally to save into an excel file, I’ll use the csv package.

# Import packages
import xml.etree.ElementTree as ET
import re
import csv

# Convert to string and remove namespace. Parse the string and return root element of Tree
xmlstring = r.text
xmlstring = re.sub(' xmlns="[^"]+"', '', xmlstring, count=1)
root = ET.fromstring(xmlstring)

# Initiate list
list = []

# For loop statement that will loop through appropriate elemental tags and return associated text content. Save that text content into dictionary and add dictionary to list.
for team in root.findall('./leagues/league/standings/teams/team'):
​ team_key = team.find('team_key')
​ team_key = team_key.text
​ name = team.find('name')
​ name = name.text
​ number_of_moves = team.find('number_of_moves')
​ number_of_moves = number_of_moves.text
​ number_of_trades = team.find('number_of_trades')
​ number_of_trades = number_of_trades.text

for nickname in team.iter('nickname'):
nickname = nickname.text
for season in team.iter('season'):
season = season.text
for points_for in team.iter('points_for'):
points_for = points_for.text
for points_against in team.iter('points_against'):
points_against = points_against.text
for rank in team.iter('rank'):
rank = rank.text
for wins in team.iter('wins'):
wins = wins.text
for losses in team.iter('losses'):
losses = losses.text
for ties in team.iter('ties'):
ties = ties.text
for playoff_seed in team.iter('playoff_seed'):
playoff_seed = playoff_seed.text

thisdict = dict(season=season, name=nickname, team_name=name, team_key=team_key, rank=rank, playoff_seed=playoff_seed, wins=wins, losses=losses, ties=ties, points_for=points_for, points_against=points_against, number_of_moves=number_of_moves, number_of_trades=number_of_trades)
list.append(thisdict)

Initially the XML had a namespace that effected the naming of elements and attributes. To make life easier, it was removed. A for loop was then written that extracted all the specified information. We stored this information in a dictionary that was subsequently added it to a list. The list is then written into a csv file.

# Generate headers for excel file.
fields = ['season', 'name', 'team_name', 'team_key', 'rank', 'playoff_seed', 'wins', 'losses', 'ties', 'points_for', 'points_against', 'number_of_moves', 'number_of_trades']

# Write contents of list into 'project.csv' saved in working directory.
with open('project.csv', 'w') as csvfile:
​ writer = csv.DictWriter(csvfile, fieldnames = fields)
​ writer.writeheader()
​ writer.writerows(list)

By utilizing this method we were able to collect 16 years worth of league metadata which included the year league was played, owner name, team name, team key, rank, playoff seed, total wins, total losses, total ties, total points scored, total points against, number of moves and number of trades.