nfl-game-data
Advanced tools
Comparing version
102
index.js
@@ -94,2 +94,36 @@ const phin = require('phin'); | ||
/** | ||
* Fetches the season data for the specified {@link seasonType}. | ||
* | ||
* @param {String} seasonType The season type we wish to retreive | ||
* ('pre', 'reg', 'post'). | ||
* @returns {Object} | ||
* @memberof NFLGameData | ||
*/ | ||
async getSeasonObject(seasonType) { | ||
const seasonData = await this.getSeasonData(); | ||
const seasonObj = seasonData.find( | ||
season => season | ||
&& season.seasonType | ||
&& season.seasonType.abbreviation === seasonType.toLowerCase(), | ||
); | ||
return seasonObj || {}; | ||
} | ||
/** | ||
* Fetches the array of play data for the specified {@link gameId} | ||
* | ||
* @static | ||
* @param {String} gameId The string representing the game ID. Looks like | ||
* '512341234' | ||
* @returns {Array} The array of play objects | ||
* @memberof NFLGameData | ||
*/ | ||
static async getPlays(gameId) { | ||
const res = await phin(NFLGameData.getPlayDataUrl(gameId)); | ||
const body = res.body.toString('utf8'); | ||
const plays = JSON.parse(body.match(NFLGameData.playDataRegex())); | ||
return plays; | ||
} | ||
/** | ||
* Gets the events object from the ESPN model for the specified | ||
@@ -109,6 +143,3 @@ * week number (game) and season type (pre, reg, post). | ||
} | ||
const seasonTypes = await this.getSeasonData(); | ||
const seasonObj = seasonTypes.find( | ||
season => season.seasonType.abbreviation === seasonType.toLowerCase(), | ||
); | ||
const seasonObj = await this.getSeasonObject(seasonType); | ||
// Post refers to events recorded after the game has ended (I think) | ||
@@ -138,6 +169,7 @@ let obj = ( | ||
*/ | ||
async getGameData(num, seasonType) { | ||
async getGame(num, seasonType) { | ||
const gameDetails = await this.getGameDetails(num, seasonType); | ||
if (gameDetails && !gameDetails.gameId) { | ||
throw new Error(`There was no game ID associated with | ||
throw new Error(` | ||
gameDetails: ${JSON.stringify(gameDetails)} | ||
TEAM: ${this.team} | ||
@@ -148,5 +180,3 @@ SEASON: ${this.season} | ||
} | ||
const res = await phin(NFLGameData.getPlayDataUrl(gameDetails.gameId)); | ||
const body = res.body.toString('utf8'); | ||
const plays = JSON.parse(body.match(NFLGameData.playDataRegex())); | ||
const plays = await NFLGameData.getPlays(gameDetails.gameId); | ||
return { | ||
@@ -159,2 +189,56 @@ plays, | ||
/** | ||
* Fetch the game details and play-by-play data from ESPN for every | ||
* game of a {@link seasonType} for the set {@link this.team} and | ||
* {@link this.season}. | ||
* | ||
* @param {String} seasonType | ||
* @returns {Object[]} | ||
* @memberof NFLGameData | ||
*/ | ||
async getEveryGame(seasonType) { | ||
const seasonObj = await this.getSeasonObject(seasonType); | ||
const games = []; | ||
const playPromises = []; | ||
let events = seasonObj && seasonObj.events && seasonObj.events.post; | ||
events = events || []; | ||
events.forEach((event) => { | ||
const gameDetails = event; | ||
gameDetails.gameId = ((event && event.time && event.time.link) || '') | ||
.split('/') | ||
.pop(); | ||
playPromises.push( | ||
new Promise((resolve) => { | ||
resolve(NFLGameData.getPlays(gameDetails.gameId)); | ||
}).then(plays => games.push({ gameDetails, plays })), | ||
); | ||
}); | ||
await Promise.all(playPromises).then(() => { | ||
games.sort((a, b) => { | ||
const aWeek = a.gameDetails.week.number || a.gameDetails.week.display; | ||
const bWeek = b.gameDetails.week.number || b.gameDetails.week.display; | ||
return aWeek - bWeek; | ||
}); | ||
}); | ||
return games; | ||
} | ||
/** | ||
* Fetch the game details and play-by-play data from ESPN for every | ||
* game of every season type. | ||
* | ||
* @returns {Object} | ||
* @memberof NFLGameData | ||
*/ | ||
async getAllGames() { | ||
const preseason = await this.getEveryGame('pre'); | ||
const regularSeason = await this.getEveryGame('reg'); | ||
const postSeason = await this.getEveryGame('post'); | ||
return { | ||
preseason, | ||
regularSeason, | ||
postSeason, | ||
}; | ||
} | ||
/** | ||
* The regular expression that captures the app data from | ||
@@ -161,0 +245,0 @@ * urlPatterns.seasonData response. |
{ | ||
"name": "nfl-game-data", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Scrapes NFL game data from ESPN", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -12,8 +12,10 @@ # NFL Game Data | ||
## Disclaimer | ||
**Disclaimer** | ||
As with all scrapers, this scraper is subject to break with any change in the response model sent back from ESPN. | ||
### `client.js` | ||
There are some occasions where the play-by-play endpoint will return a one-off response that doesn't contain the model that the scraper's regex is expecting. So far I've only seen it with a single preseason game. I don't care enough to parse the raw HTML. Sorry! Fork this repo and enhance it if you'd like. | ||
## `Usage` | ||
```javascript | ||
@@ -23,9 +25,44 @@ const NFLGameData = require("nfl-game-data"); | ||
// Set team (Seattle Seahawks) and season year (2018). | ||
const nflGameData = new NFLGameData("sea", 2018); | ||
const nflGameData = new NFLGameData('sea', 2018); | ||
// Fetch game data for game 3 of the regular season. | ||
nflGameData.getGameData(3, "reg").then(response => { | ||
const { plays, gameDetails } = response; | ||
/** | ||
* Fetch game data for game 3 of the regular season. | ||
* | ||
* HTTP Request count: | ||
* 1 (season data) + 1 game (for plays) | ||
*/ | ||
nflGameData.getGame(3, 'reg').then((data) => { | ||
const { plays, gameDetails } = data; | ||
// Do something... | ||
}); | ||
// Change team to New England Patriots | ||
nflGameData.team = 'ne'; | ||
// Change season to 2017 | ||
nflGameData.season = 2017; | ||
/** | ||
* Fetch game data for every game of the Regular Season | ||
* | ||
* HTTP Request count: | ||
* 1 (season data) + N games (plays for each game) | ||
*/ | ||
nflGameData.getEveryGame('reg').then((regSeasonGames) => { | ||
regSeasonGames.forEach(({ plays, gameDetails }) => { | ||
// Do something... | ||
}); | ||
}); | ||
/** | ||
* Fetch game data for every game of every season type | ||
* | ||
* HTTP Request count: | ||
* 1 (season data) + N games (plays for each game) for each season | ||
*/ | ||
nflGameData.getAllGames().then((allGames) => { | ||
const { preseason, regularSeason, postSeason } = allGames; | ||
regularSeason.forEach(({ plays, gameDetails }) => { | ||
// Do something... | ||
}); | ||
}); | ||
``` | ||
@@ -32,0 +69,0 @@ |
13446
36.16%273
41.45%170
27.82%