Первоначально опубликовано на ScraperAPI.

HTML-таблицы являются лучшими источниками данных в Интернете. Они просты для понимания и могут содержать огромное количество данных в простом для чтения и понимания формате. Умение очищать HTML-таблицы — важный навык для любого разработчика, интересующегося наукой о данных или анализом данных в целом.

В этом руководстве мы углубимся в HTML-таблицы и создадим простой, но мощный скрипт для извлечения табличных данных и экспорта их в файл CSV.

Что такое веб-таблица HTML?

HTML-таблица — это набор строк и столбцов, которые используются для отображения информации в формате сетки непосредственно на веб-странице. Они обычно используются для отображения табличных данных, таких как электронные таблицы или базы данных, и являются отличным источником данных для наших проектов.

От спортивных данных и данных о погоде до книг и данных авторов, большинство больших наборов данных в Интернете доступны через таблицы HTML из-за того, насколько они хороши для отображения информации в структурированном и удобном для навигации формате.

Хорошая новость для нас заключается в том, что, в отличие от динамически генерируемого контента, данные таблицы HTML находятся непосредственно внутри элемента таблицы в файле HTML, а это означает, что мы можем извлечь всю необходимую информацию точно так же, как и с другими элементами сети — пока мы понимаем их структуру.

Понимание структуры таблицы HTML

Хотя вы можете видеть только столбцы и строки во внешнем интерфейсе, эти таблицы на самом деле создаются с использованием нескольких различных тегов HTML:

  • : отмечает начало HTML-таблицы.
  • : указывает строку в таблице
  • <td>: определяет ячейку в таблице

Содержимое помещается внутри тега <td>, а <tr> используется для создания строки. Другими словами: Таблица › Строка › Ячейка || Для создания HTML-таблицы используется иерархия table › tr › td.

Специальную ячейку можно создать с помощью тега <th>, что означает заголовок таблицы. По сути, первые ячейки первой строки можно создать с помощью тега <th>, чтобы указать, что строка является заголовком таблицы.

Вот пример создания простой HTML-таблицы с двумя строками и двумя столбцами:

Однако есть одно существенное отличие при парсинге HTML-таблиц. В отличие от других элементов на веб-странице, селекторы CSS нацелены на все ячейки и строки — или даже на всю таблицу — потому что все эти элементы на самом деле являются компонентами элемента <table>.

Вместо того, чтобы нацеливаться на селектор CSS для каждой точки данных, которую мы хотим очистить, нам нужно создать список со всеми строками таблицы и пройтись по ним, чтобы получить данные из их ячеек.

Если мы понимаем эту логику, создание нашего сценария на самом деле довольно просто.

Скрапинг HTML-таблиц в CSV с помощью Node.JS

Если вы впервые используете Node.JS для парсинга веб-страниц, может быть полезно пройти некоторые из наших предыдущих руководств:

Тем не менее, мы постараемся сделать это руководство максимально удобным для начинающих, чтобы вы могли использовать его даже в качестве отправной точки.

Примечание. Инструкции по установке Node.JS см. в первой статье списка.

Для сегодняшнего проекта мы создадим веб-скребок, используя Axios и Cheerio, для очистки данных о сотрудниках, отображаемых на https://datatables.net/examples/styling/display.html.

Мы будем извлекать имя, должность, должность, возраст, дату начала работы и зарплату для каждого сотрудника, а затем отправлять данные в CSV с помощью пакета ObjectsToCsv.

1. Подготовка наших файлов

Чтобы запустить наш проект, давайте создадим новый каталог с именем html-table-scraper, откроем новую папку в VScode (или в предпочитаемом вами редакторе кода) и откроем новый терминал.

В терминале мы запустим npm init -y, чтобы запустить новый проект Node.JS. Теперь у вас будет новый файл JSON в вашей папке.

Далее мы установим наши зависимости, используя следующие команды:

  • Аксиос: npm install axios
  • Здорово: npm install cheerio
  • ObjectsToCsv: npm install objects-to-csv

Наш для установки одной командой: npm i axios cheerio objects-to-csv.

Теперь мы можем создать новый файл с именем tablescraper.js и импортировать наши зависимости сверху.

Кроме того, ваш проект должен выглядеть так:

2. Тестирование целевого сайта с помощью DevTools

Прежде чем писать код, нам нужно понять, как устроен сайт. Да, все таблицы используют базовую структуру, но это не значит, что все они созданы одинаково.

Первое, что нам нужно определить, это действительно ли это HTML-таблица. Сайты очень часто используют JavaScript для ввода данных в свои таблицы, особенно если речь идет о каких-либо данных в реальном времени. В этих случаях нам пришлось бы использовать совершенно другой подход, например, использование безголового браузера.

Чтобы проверить, находятся ли данные в файле HTML, все, что нам нужно сделать, это скопировать некоторые точки данных — скажем, имя — и найти их в исходном коде страницы.

Мы сделали то же самое для других имен и точек данных, просто чтобы убедиться, и да, все данные прямо в нашем распоряжении. Еще одним интересным сюрпризом является то, что все строки таблицы находятся внутри необработанного HTML, даже несмотря на то, что во внешнем интерфейсе есть какая-то нумерация страниц.

Кроме того, теперь мы также знаем, что всего нужно очистить 57 строк. Это важно, потому что мы можем знать, действительно ли мы собираем все доступные данные.

Второе, что мы хотим протестировать прямо в браузере, — это наши селекторы. Вместо того, чтобы отправлять кучу ненужных запросов, мы можем использовать консоль браузера для захвата элементов с помощью document.querySelectorAll() method.

Если мы перейдем к консоли и наберем document.querySelectorAll('table'), она вернет четыре разные таблицы.

Наведя курсор на таблицы, мы быстро поняли, что первая таблица (номер 0) — правильная. Итак, давайте сделаем это снова, но указав класс, который в списке представлен точками (.).

Отлично, мы на шаг ближе к нашим данным!

При более внимательном рассмотрении данные таблицы обернуты вокруг тега <tbody>, поэтому давайте добавим его в наш селектор, чтобы убедиться, что мы захватываем только строки, содержащие нужные нам данные.

Наконец, мы хотим получить все строки и убедиться, что наш селектор захватывает все 57 строк.

Примечание. Поскольку мы используем консоль для выбора элементов в отображаемом HTML-коде, нам нужно было установить общее количество отображаемых элементов равным 100. В противном случае наш селектор на консоли будет отображать только 10 узловых элементов.

Со всей этой информацией мы можем начать писать наш код!

3. Отправка нашего HTTP-запроса и анализ необработанного HTML

Axios упрощает отправку HTTP-запросов внутри файла Async Function. Все, что нам нужно сделать, это создать асинхронную функцию и передать URL-адрес Axios в константе с именем response. Мы также будем регистрировать код состояния ответа (который должен быть 200 для успешного запроса).

Примечание. Вы можете назвать эти переменные как хотите, но старайтесь, чтобы они были как можно более описательными.

Затем мы сохраним данные из ответа (необработанный HTML) в новую константу с именем html, чтобы затем передать ее в Cheerio для анализа с помощью cheerio.load().

4. Перебор строк HTML-таблицы

Используя селектор, который мы тестировали ранее, давайте выберем все строки внутри HTML-таблицы.

В целях тестирования давайте console.log() длину allRows, чтобы убедиться, что мы действительно выбрали все наши целевые строки.

57 — это именно то, к чему мы стремились!

Конечно, чтобы просмотреть список строк, мы будем использовать метод .each(), но нам нужно выяснить еще одну вещь: порядок ячеек.

В отличие от обычных HTML-элементов, ячейкам не назначается уникальный класс. Таким образом, попытка очистить каждую точку данных с помощью класса CSS может привести к беспорядку. Вместо этого мы нацелимся на позицию <td>s в своей строке.

Другими словами, мы скажем нашему сценарию перейти к каждой строке, выбрать все ячейки внутри строки, а затем сохранить каждую точку данных в переменной в зависимости от ее положения в строке.

Примечание. В Node.JS все списки начинаются с 0. Таким образом, первая позиция будет [0], а вторая ячейка — [1].

Но как узнать, какая позиция какая? Возвращаемся в консоль нашего браузера и тестируем:

Теперь, когда мы знаем, где каждый элемент находится по отношению к остальным, вот готовый синтаксический анализатор:

5. Перемещение очищенных данных в пустой массив

Если мы console.log() очистим данные, мы увидим, что мы удаляем текст из каждой ячейки, но с очень неорганизованными результатами, что, в свою очередь, затрудняет создание нашего CSV-файла.

Итак, прежде чем мы экспортируем наши данные, давайте упорядочим их, поместив данные в пустой массив, чтобы создать простой список узлов.

Во-первых, создайте пустой массив вне основной функции — если вы создадите пустой массив внутри функции, он будет перезаписываться при каждой итерации, а это не то, чего мы хотим.

Затем, как часть нашего синтаксического анализатора, давайте воспользуемся методом .push() для сохранения наших данных в пустом списке, который мы создали.

Как всегда, давайте console.log() увеличим длину файла employeeData, чтобы убедиться, что теперь в нем 57 элементов.

Для визуального контекста мы также можем зарегистрировать массив, чтобы увидеть, что хранится внутри.

Как мы видим, все данные теперь хранятся внутри элементов узла, которые содержат каждый фрагмент данных в структурированном формате.

6. Отправка очищенных данных в CSV-файл

Организовав наши данные, мы можем передать наш список в ObjectsToCsv, и он создаст для нас файл без дополнительной работы:

Все, что нам нужно сделать, это создать новый объект csv и передать список в ObjectsToCsv, а затем указать ему сохранить его на нашей машине, указав путь.

7. Парсер HTML-таблиц [полный код]

Поздравляем, вы официально создали свой первый парсер HTML-таблиц! Сравните свой код с готовой кодовой базой этого руководства, чтобы убедиться, что вы ничего не пропустили:

После запуска нашего скрипта в папке нашего проекта создается новый CSV-файл:

Теперь вы можете использовать эти данные для дальнейшего анализа, например, для сравнения окладов на основе названия должности или даты начала работы, или для поиска тенденций в больших наборах данных о должностях.

Конечно, этот скрипт можно адаптировать для работы практически с любой HTML-таблицей, которую вы найдете, так что будьте открыты для новых возможностей и возможностей.

Избегайте блокировки: интеграция ScraperAPI в одну строку кода

Прежде чем вы уйдете, нам нужно сделать еще одну вещь, чтобы сделать наш скребок более устойчивым, и это обработка методов и систем защиты от скраба. Многим веб-сайтам не нравится, когда их очищают, потому что, к сожалению, многие парсеры плохо оптимизированы и имеют тенденцию наносить вред их сайтам.

По этой причине вам необходимо следовать некоторым рекомендациям веб-скрапинга, чтобы убедиться, что вы правильно обрабатываете свои проекты, не оказывая слишком большого давления на целевой веб-сайт и не подвергая свой скрипт и IP риску бана или внесения в черный список — что делает невозможным повторный доступ к необходимым данным с вашего компьютера.

Для управления ротацией IP-адресов, рендерингом JavaScript, нахождением и внедрением HTTP-заголовков, CAPTCHA и многим другим, все, что нам нужно сделать, это отправить наш первоначальный запрос через сервер ScraperAPI. Этот API будет использовать годы статистического анализа и машинного обучения, чтобы определить, какая комбинация заголовков и прокси-сервера является лучшей, обрабатывать любые неудачные запросы и рассчитывать время нашего запроса, чтобы он не перегружал наш целевой сервер.

Добавить его в наш скрипт так же просто, как добавить эту строку к URL-адресу, переданному в Axios:

Не забудьте заменить {Your_API_Key} своим собственным ключом API, который вы можете сгенерировать, создав бесплатную учетную запись ScraperAPI.

Ваш первоначальный запрос займет немного больше времени, пока ScraperAPI справится со всеми сложностями за вас, и будет использовать кредиты API только для успешных запросов.

Теперь твоя очередь. Веб-скрапинг — это практика. Каждый веб-сайт — это отдельная головоломка, поэтому нет единого способа сделать что-то. Вместо этого сосредоточьтесь на использовании основ для решения более сложных задач.

Если вы хотите продолжать практиковаться, мы рекомендуем несколько веб-сайтов:

До следующего раза, счастливого соскабливания!