Replace cheerio with jsdom.

This commit is contained in:
maxswa
2020-07-23 18:13:51 -04:00
parent eaa3d4a299
commit 8d065742d0
4 changed files with 276 additions and 411 deletions

View File

@@ -37,11 +37,11 @@
"homepage": "https://github.com/maxswa/osrs-json-hiscores#readme",
"dependencies": {
"axios": "^0.19.0",
"cheerio": "^1.0.0-rc.3"
"jsdom": "^16.3.0"
},
"devDependencies": {
"@types/cheerio": "^0.22.11",
"@types/jest": "^24.0.14",
"@types/jsdom": "^16.2.3",
"jest": "^24.8.0",
"np": "^5.0.3",
"prettier": "^1.19.1",

View File

@@ -1,5 +1,4 @@
import axios from 'axios';
import * as cheerio from 'cheerio';
import {
Player,
Activity,
@@ -14,7 +13,6 @@ import {
ActivityName,
PlayerActivityRow,
Bosses,
Boss,
} from './types';
import {
getStatsURL,
@@ -30,6 +28,7 @@ import {
getActivityPageURL,
BOSSES,
} from './utils';
import { JSDOM } from 'jsdom';
export async function getStats(rsn: string): Promise<Player> {
if (typeof rsn !== 'string') {
@@ -145,22 +144,26 @@ export async function getSkillPage(
const url = getSkillPageURL(mode, skill, page);
const response = await axios(url);
const $ = cheerio.load(response.data);
const playersHTML = $('.personal-hiscores__row').toArray();
const dom = new JSDOM(response.data);
const playersHTML = dom.window.document.querySelectorAll(
'.personal-hiscores__row'
);
const players: PlayerSkillRow[] = playersHTML.map(row => {
const cells = row.children.filter(el => el.name === 'td');
const [rankEl, nameCell, levelEl, xpEl] = cells;
const nameEl = nameCell.children.find(el => el.name === 'a');
const isDead = !!nameCell.children.find(el => el.name === 'img');
const players: PlayerSkillRow[] = [];
playersHTML.forEach(row => {
const rankEl = row.querySelector('td');
const nameEl = row.querySelector('td a');
const levelEl = row.querySelector('td.left + td');
const xpEl = row.querySelector('td.left + td + td');
const isDead = !!row.querySelector('td img');
return {
players.push({
name: rsnFromElement(nameEl),
rank: numberFromElement(rankEl),
level: numberFromElement(levelEl),
xp: numberFromElement(xpEl),
dead: isDead,
};
});
});
return players;
@@ -181,21 +184,24 @@ export async function getActivityPage(
const url = getActivityPageURL(mode, activity, page);
const response = await axios(url);
const $ = cheerio.load(response.data);
const playersHTML = $('.personal-hiscores__row').toArray();
const dom = new JSDOM(response.data);
const playersHTML = dom.window.document.querySelectorAll(
'.personal-hiscores__row'
);
const players: PlayerActivityRow[] = playersHTML.map(row => {
const cells = row.children.filter(el => el.name === 'td');
const [rankEl, nameCell, scoreEl] = cells;
const nameEl = nameCell.children.find(el => el.name === 'a');
const isDead = !!nameCell.children.find(el => el.name === 'img');
const players: PlayerActivityRow[] = [];
playersHTML.forEach(row => {
const rankEl = row.querySelector('td');
const nameEl = row.querySelector('td a');
const scoreEl = row.querySelector('td.left + td');
const isDead = !!row.querySelector('td img');
return {
players.push({
name: rsnFromElement(nameEl),
rank: numberFromElement(rankEl),
score: numberFromElement(scoreEl),
dead: isDead,
};
});
});
return players;
@@ -213,10 +219,13 @@ export async function getRSNFormat(rsn: string): Promise<string> {
const url = getPlayerTableURL('main', rsn);
try {
const response = await axios(url);
const $ = cheerio.load(response.data);
const rawName = $('[style="color:#AA0022;"]')[1].children[0].data;
if (rawName) {
return rawName.replace(/\uFFFD/g, ' ');
const dom = new JSDOM(response.data);
const spans = dom.window.document.querySelectorAll(
'span[style="color:#AA0022;"]'
);
if (spans.length >= 2) {
const nameSpan = spans[1];
return rsnFromElement(nameSpan);
}
throw Error('Player not found');
} catch {

View File

@@ -35,13 +35,13 @@ export const getActivityPageURL = (
activity
)}&page=${page}`;
export const numberFromElement = (el: CheerioElement) => {
const innerText = el.firstChild.data;
const number = innerText ? innerText.replace(/[\n|,]/g, '') : '-1';
export const numberFromElement = (el: Element | null) => {
const { innerHTML } = el || {};
const number = innerHTML?.replace(/[\n|,]/g, '') ?? '-1';
return parseInt(number, 10);
};
export const rsnFromElement = (el: CheerioElement | undefined) => {
const innerText = el?.firstChild.data;
return innerText ? innerText.replace(/\uFFFD/g, ' ') : '';
export const rsnFromElement = (el: Element | null) => {
const { innerHTML } = el || {};
return innerHTML?.replace(/\uFFFD/g, ' ') || '';
};

614
yarn.lock

File diff suppressed because it is too large Load Diff