ufc-scraper
Advanced tools
Comparing version 0.1.0 to 0.1.6
{ | ||
"name": "ufc-scraper", | ||
"version": "0.1.0", | ||
"description": "An API to scrape UFC fighter information, statistics, and rankings from UFC.com", | ||
"version": "0.1.6", | ||
"description": "An API to scrape UFC fighter information, statistics, records, and rankings from UFC.com", | ||
"main": "dist/ufc_scraper.js", | ||
@@ -20,2 +20,3 @@ "types": "dist/types/ufc_scraper.d.ts", | ||
"UFC Stats", | ||
"UFC Records", | ||
"MMA Stats" | ||
@@ -22,0 +23,0 @@ ], |
142
README.md
# UFC Scraper | ||
<img src="https://upload.wikimedia.org/wikipedia/commons/d/d7/UFC_Logo.png" width="250"/> | ||
https://www.npmjs.com/package/ufc-scraper | ||
## Overview | ||
The `ufc-scraper` package provides a set of functions to scrape UFC fighter information, statistics, and rankings from the UFC website. It uses `axios` for making HTTP requests and `cheerio` for parsing HTML content. This package enables you to programmatically retrieve detailed UFC fighter data, including fight history, personal stats, and official rankings. | ||
The `ufc-scraper` package provides a set of functions to scrape UFC fighter information, statistics, and rankings from the UFC website. It uses `axios` for making HTTP requests and `cheerio` for parsing HTML content. This package enables you to programmatically retrieve detailed UFC fighter data, including fighter information, statistics, records, and official rankings. | ||
@@ -84,2 +85,34 @@ ## Installation | ||
### `getTitleholders` | ||
Retrieves the current UFC titleholders, categorized by division. | ||
```typescript | ||
import { getTitleholders } from 'ufc-scraper'; | ||
getTitleholders().then(titleholders => { | ||
if (titleholders) { | ||
console.log(titleholders); | ||
} else { | ||
console.log('Failed to retrieve titleholders.'); | ||
} | ||
}); | ||
``` | ||
### `getRecords` | ||
Retrieves UFC career records and statistics across various categories. | ||
```typescript | ||
import { getRecords } from 'ufc-scraper'; | ||
getRecords().then(records => { | ||
if (records) { | ||
console.log(records); | ||
} else { | ||
console.log('Failed to retrieve records.'); | ||
} | ||
}); | ||
``` | ||
## Functions | ||
@@ -99,6 +132,12 @@ | ||
### `getRankings(): Promise<RankingsDict | null>` | ||
### `getRankings(): Promise<Rankings | null>` | ||
Retrieves the current UFC rankings, categorized by weight class. | ||
### `getTitleholders(): Promise<Titleholders | null>` | ||
Retrieves the current UFC titleholders, categorized by division. | ||
### `getRecords(): Promise<Records | null>` | ||
Retrieves UFC career records and statistics across various categories. | ||
## Interfaces | ||
@@ -178,2 +217,29 @@ | ||
### `Titleholders` | ||
```typescript | ||
interface Titleholders { | ||
[Division: string]: { | ||
Weight: string; | ||
ChampName: string; | ||
ChampNickname: string; | ||
ChampRecord: string; | ||
ChampLastFight: string; | ||
}; | ||
} | ||
``` | ||
### 'Records' | ||
```typescript | ||
interface Records { | ||
[Category: string]: { | ||
[Rank: number]: { | ||
Fighter: string; | ||
Statistic: string; | ||
} | ||
}; | ||
} | ||
``` | ||
## Error Handling | ||
@@ -188,3 +254,3 @@ | ||
```typescript | ||
import { getFighter, getRankings } from 'ufc-scraper'; | ||
import { getFighter, getRankings, getTitleholders, getRecords } from 'ufc-scraper'; | ||
@@ -248,35 +314,40 @@ getFighter('max holloway').then((fighter) => { | ||
}, | ||
etc... | ||
} | ||
*/ | ||
getTitleholders().then((titleholders) => { | ||
console.log(titleholders); | ||
}); | ||
/* Returns the following: | ||
{ | ||
Flyweight: { | ||
'1': 'Brandon Royval', | ||
'2': 'Brandon Moreno', | ||
'3': 'Amir Albazi', | ||
'4': 'Kai Kara-France', | ||
'5': 'Alex Perez', | ||
'6': 'Muhammad Mokaev', | ||
'7': 'Manel Kape', | ||
'8': 'Matheus Nicolau', | ||
'9': 'Steve Erceg', | ||
'10': 'Tim Elliott', | ||
'11': 'Matt Schnell', | ||
'12': 'Tagir Ulanbekov', | ||
'13': 'Tatsuro Taira', | ||
'14': 'Sumudaerji', | ||
'15': 'David Dvorak' | ||
Weight: '125 lb (56.82 kg)', | ||
ChampName: 'Alexandre Pantoja', | ||
ChampNickname: '"The Cannibal"', | ||
ChampRecord: '28-5-0 (W-L-D)', | ||
ChampLastFight: 'Alexandre Pantoja vs Steve Erceg' | ||
}, | ||
Bantamweight: { | ||
'1': 'Merab Dvalishvili', | ||
'2': 'Cory Sandhagen', | ||
'3': 'Petr Yan', | ||
'4': 'Marlon Vera', | ||
'5': 'Henry Cejudo', | ||
'6': 'Deiveson Figueiredo', | ||
'7': 'Song Yadong', | ||
'8': 'José Aldo', | ||
'9': 'Rob Font', | ||
'10': 'Umar Nurmagomedov', | ||
'11': 'Kyler Phillips', | ||
'12': 'Mario Bautista', | ||
'13': 'Dominick Cruz', | ||
'14': 'Jonathan Martinez', | ||
'15': 'Pedro Munhoz' | ||
etc... | ||
} | ||
*/ | ||
getRecords().then((records) => { | ||
console.log(records); | ||
}); | ||
/* Returns the following: | ||
{ | ||
'Total Fights': { | ||
'1': { Fighter: 'Jim Miller', Statistic: '44' }, | ||
'2': { Fighter: 'Andrei Arlovski', Statistic: '41' }, | ||
'3': { Fighter: 'Donald Cerrone', Statistic: '38' }, | ||
'4': { Fighter: 'Clay Guida', Statistic: '36' }, | ||
'5': { Fighter: 'Rafael Dos Anjos', Statistic: '35' }, | ||
'6': { Fighter: 'Jeremy Stephens', Statistic: '34' }, | ||
'7': { Fighter: 'Demian Maia', Statistic: '33' }, | ||
'8': { Fighter: 'Charles Oliveira', Statistic: '33' }, | ||
'9': { Fighter: 'Diego Sanchez', Statistic: '32' }, | ||
'10': { Fighter: 'Neil Magny', Statistic: '32' } | ||
}, | ||
@@ -294,3 +365,2 @@ etc... | ||
Contributions are welcome! Please open an issue or submit a pull request if you have any improvements or bug fixes. | ||
Contributions are welcome! Please open an issue or submit a pull request if you have any improvements or bug fixes. |
135
src/index.ts
import axios from 'axios'; | ||
import * as cheerio from 'cheerio'; | ||
import { FighterStats } from './interfaces/fighter_stats'; | ||
import { FighterInfo } from './interfaces/fighter_info'; | ||
import { Fighter } from './interfaces/fighter'; | ||
interface Fighter { | ||
FighterInfo: FighterInfo | null; | ||
FighterStats: FighterStats | null; | ||
} | ||
export async function getFighter(fighterName: string = 'max holloway'): Promise<Fighter | null> { | ||
try { | ||
let [fighterInfo, fighterStats] = await Promise.all([ | ||
getFighterInfo(fighterName), | ||
getFighterStats(fighterName) | ||
]); | ||
return { | ||
FighterInfo: await getFighterInfo(fighterName), | ||
FighterStats: await getFighterStats(fighterName), | ||
} | ||
FighterInfo: fighterInfo, | ||
FighterStats: fighterStats | ||
}; | ||
} catch (error) { | ||
@@ -19,2 +26,19 @@ console.error(`Error scraping UFC.com : ${error}`); | ||
interface FighterInfo { | ||
Name: string; | ||
Nickname: string; | ||
Status: string; | ||
Age: string; | ||
Height: string; | ||
Weight: string; | ||
ArmReach: string; | ||
LegReach: string; | ||
FightingStyle: string; | ||
Division: string; | ||
PlaceOfBirth: string; | ||
TrainingCamp: string; | ||
OctagonDebut: string; | ||
ImageURL: string | undefined; | ||
} | ||
export async function getFighterInfo(fighterName: string = 'max holloway'): Promise<FighterInfo | null> { | ||
@@ -67,2 +91,12 @@ const formattedName = fighterName.replace(' ', '-').toLowerCase(); | ||
interface FighterStats { | ||
Record: string; | ||
WinByMethod: { KO: string, Decision: string, Submission: string }; | ||
AvgFightTime: string; | ||
SigStrikeByPosition: {Standing: string, Clinch: string, Ground: string}; | ||
SigStrikeByTarget: {Head: string, Body: string, Leg: string}; | ||
StrikingAccuracy: {SigStrikesLanded: string, SigStrikesAttempted: string}; | ||
TakedownAccuracy: {TakedownsLanded: string, TakedownsAttempted: string}; | ||
} | ||
export async function getFighterStats(fighterName: string = 'max holloway'): Promise<FighterStats| null> { | ||
@@ -118,3 +152,3 @@ const formattedName = fighterName.replace(' ', '-').toLowerCase(); | ||
interface Rankings { | ||
[Division: string]: { [rank: number]: string }; | ||
[Division: string]: { [Rank: number]: string }; | ||
} | ||
@@ -133,3 +167,3 @@ | ||
let header = $(element).find('.view-grouping-header').text().trim(); | ||
let rankings: { [rank: number]: string } = {}; | ||
let rankings: { [Rank: number]: string } = {}; | ||
@@ -150,2 +184,87 @@ $(element).find('tbody tr').each((j, row) => { | ||
} | ||
} | ||
interface Titleholders { | ||
[Division: string]: { | ||
Weight: string; | ||
ChampName: string; | ||
ChampNickname: string; | ||
ChampRecord: string; | ||
ChampLastFight: string; | ||
}; | ||
} | ||
export async function getTitleholders(): Promise<Titleholders | null> { | ||
const url = 'https://www.ufc.com/athletes'; | ||
try { | ||
const { data } = await axios.get(url); | ||
const $ = cheerio.load(data); | ||
let titleholdersDict: Titleholders = {}; | ||
$('.l-listing__item').each((i, element) => { | ||
let division = $(element).find('.ath-wlcass strong').text().trim(); | ||
let weight = $(element).find('.ath-weight').text().trim(); | ||
let champName = $(element).find('.ath-n__name a span').text().trim(); | ||
let champNickname = $(element).find('.ath-nn__nickname .field__item').text().trim(); | ||
let champRecord = $(element).find('.c-ath--record').text().trim(); | ||
let champLastFight = $(element).find('.view-fighter-last-fight .view-content .views-row').first().text().trim(); | ||
if (division) { | ||
titleholdersDict[division] = { | ||
Weight: weight, | ||
ChampName: champName, | ||
ChampNickname: champNickname, | ||
ChampRecord: champRecord, | ||
ChampLastFight: champLastFight, | ||
}; | ||
} | ||
}); | ||
return titleholdersDict; | ||
} catch (error) { | ||
console.error(`Error scraping UFC.com : ${error}`); | ||
return null; | ||
} | ||
} | ||
interface Records { | ||
[Category: string]: { | ||
[Rank: number]: { | ||
Fighter: string; | ||
Statistic: string; | ||
} | ||
}; | ||
} | ||
export async function getRecords(): Promise<Records | null> { | ||
const url = 'http://statleaders.ufc.com/en/career'; | ||
try { | ||
const { data } = await axios.get(url); | ||
const $ = cheerio.load(data); | ||
let recordsDict: Records = {}; | ||
$('.results-group').each((i, element) => { | ||
let category = $(element).find('header h3').text().trim(); | ||
recordsDict[category] = {}; | ||
$(element).find('.results-table--tr:not(.results-table--th)').each((index, row) => { | ||
let rank = index + 1; | ||
let fighter = $(row).find('span').eq(1).text().trim(); | ||
let total = $(row).find('span').eq(2).text().trim(); | ||
if (rank && fighter && total) { | ||
recordsDict[category][rank] = { Fighter: fighter, Statistic: total }; | ||
} | ||
}); | ||
}); | ||
return recordsDict; | ||
} catch (error) { | ||
console.error(`Error scraping UFC.com: ${error}`); | ||
return null; | ||
} | ||
} |
30161
464
360
14