Статья посвящена созданию приложения для поиска данных игрока NHL на разных ресурсах. Используя стек Node.js и наработки по вебскрапингу будем создавать онлайн приложение для поиска данных.
Для одного из моих проектов понадобилась система для поиска игрока NHL по имени и фамилии нужно найти :
- Дату рождения
- Вес рост
- Позиция
- Хват клюшки
- Клуб
Как самое простое решение использовал страницы Википедии.

Пример как выглядит блок с этой информацией
Используя стек Node.js + Cherrio получил такой код (парсинг) :
parse() {
const info = $('table.infobox', this.responseBody);
if (info.length) {
const tbody = info[0].children[0];
tbody.children.forEach((row, index) => {
const th = row.children[0] || null;
const td = row.children[1] || null;
if (th && td) {
const rowTitle = this.getRowText(th) || null;
const rowData = this.getRowText(td) || null;
if (rowTitle.length > 0 && rowData.length > 0) {
switch (rowTitle[0]) {
case 'Height':
this.setHeight(rowData[0]);
break;
case 'Weight':
this.setWeight(rowData[0]);
break;
case 'Position':
this.setPosition(rowData[0]);
break;
case 'Shot':
this.setShot(rowData[0]);
break;
case 'Born':
this.setBorn(this.detectDate(rowData));
break;
}
}
}
});
} else {
this.error = 'No table';
}
}
Функция определения роста:
setHeight(stringHeight) {
const height = (stringHeight.indexOf('(') > -1 && stringHeight.indexOf(')') > -1) ?
this.getParentheses(stringHeight) : ['', stringHeight];
this.playerInfo[this.playersCount].setHeight(this.normalzeHeight(height[1]));
}
Функция определения веса:
setWeight(stringWeight) {
const weight = (stringWeight.indexOf('(') > -1 && stringWeight.indexOf(')') > -1) ?
this.getParentheses(stringWeight) : ['', stringWeight];
this.playerInfo[this.playersCount].setWeight(this.normalzeWidth(weight[1]));
}
Функция определения позиции:
setPosition(stringPosition) {
this.playerInfo[this.playersCount].setPosition(stringPosition || '');
}
Функция определения хвата:
setShot(stringShot) {
this.playerInfo[this.playersCount].setShot(stringShot || '');
}
Функция определения даты рождения:
setBorn(stringBorn) {
this.playerInfo[this.playersCount].setBorn(stringBorn || null);
}
Выбор даты по формату (использовал библиотеку для работы с датами Luxon):
detectDate(list) {
let res = null;
for (const item of list) {
const dt = DateTime.fromFormat(item, 'LLLL dd, yyyy');
if (dt.isValid) {
res = item;
break;
}
}
return res;
}
Класс игрока:
class Player {
constructor(names) {
if (this.schema(names)) {
const {firstName, lastName} = names;
this.name = firstName;
this.surname = lastName;
} else {
this.name = '';
this.surname = '';
}
this.born = null;
this.height = 0;
this.weight = 0;
this.shot = '';
this.position = '';
}
setBorn(stringBorn) {
this.born = stringBorn;
}
setHeight(stringHeight) {
this.height = stringHeight;
}
setWeight(stringWeight) {
this.weight = stringWeight;
}
setShot(stringShot) {
this.shot = stringShot;
}
setPosition(stringPosition) {
this.position = stringPosition;
}
show() {
console.group('PlayerInfo');
console.info(` Player ${this.name} ${this.surname}`);
if (this.checkEmpty()) {
console.info(` Born ${this.born} `);
console.info(` Height ${this.height} `);
console.info(` Weight ${this.weight} `);
console.info(` Shot ${this.shot} `);
console.info(` Position ${this.position} `);
}
console.groupEnd('PlayerInfo');
}
clear() {
this.born = null;
this.height = 0;
this.weight = 0;
this.shot = '';
this.position = '';
}
checkEmpty() {
return this.born || this.height || this.weight || this.shot || this.position;
}
schema(names) {
let res = false;
if (names && names.firstName && names.lastName) {
res = true;
}
return res;
}
}
Плюс страниц Википедии:
- Легко доступна и не блокируется
- Понятная и редко изменяемая структура
Минусы страниц Википедии в том что :
- Могут быть страницы с однофамильцами и тогда ссылка на страницу может содержать — /wiki/Dallas_Smith_(ice_hockey)
- Могут просто отсутвовать так как Википедию всё-таки редактируют волонтёры.
Статья с описанием схемы проиложения по ссылке
Исходники — ice-hockey-player-searcher
В следующих статьях :
- Создам простой сервер и форму для выполнения запроса
- Загрузим это всё на Heroku чтобы можно было удалённо пользоваться
- Добавим резервный ресурс для поиска (не только Википедия)
- Добавим прокси, чтобы не получать бан