Создание ресурса для поиска игроков NHL

Статья посвящена созданию приложения для поиска данных игрока 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

В следующих статьях :


Опубликовано

в

от

Метки:

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.