Puppeteer: не просто очередная библиотека для парсинга
Puppeteer – это библиотека Node.js, поддерживаемая командой Chrome Devtools. Библиотека запускает экземпляр Chrome/Chromium и предоставляет набор высокоуровневых API.
Puppeteer используется для выполнения множества различных задач:
- автоматизация сбора данных с веб-сайтов;
- создание скриншотов и PDF-файлов;
- тестирование расширений Chrome;
- автоматизация тестирования веб-интерфейсов;
- диагностика проблем производительности с помощью таких методов, как захват временной шкалы трассировки веб-сайта.
В сравнении с Selenium библиотека Puppeteer не обладает кросс-браузерностью, но часто выигрывает в скорости, так как не имеет промежуточного звена в виде Selenium server – команды идут напрямую в браузер.
В этой статье мы рассмотрим пример сбора данных с одной из страниц Amazon со списком товаров. Извлечем информацию из страницы списка лучших рубашек, поместим в JSON и посмотрим, как эмулировать действия пользователя (поиск товара). Полный код проекта доступен в репозитории.
Установка Puppeteer и навигация
Puppeteer без проблем устанавливается с помощью npm:
Создадим экземпляр браузера и страницы, перейдем к целевому URL-адресу:
Назначение экземпляров интуитивно понятно:
browser
: запускает экземпляр Chrome при вызовеpuppeteer.launch
. Простая эмуляция браузера.page
: напоминает одну вкладку в браузере Chrome. Предоставляет набор методов, которые можно применить к конкретному экземпляру страницы/ Вызывается при запускеbrowser.newPage
. Как в браузере можно создать несколько вкладок, так в Puppeteer можно одновременно обрабатывать несколько экземпляров страниц.
В качестве значения параметра waitUntil
используем networkidle2
. Это гарантирует, что состояние загрузки страницы считается
окончательным, если она имеет не более 2 подключений, работающих в течение не
менее 500 мс.
Собираем данные со страницы
Выясним, какие данные необходимо извлечь. Нас интересует бренд, название продукта, ссылки на продукт и его изображение, и, наконец, стоимость:
Для запроса DOM используем метод page.evaluate()
. Для обхода DOM – обычные методы JavaScript document.querySelector
и document.querySelectorAll
.
После изучения DOM стало ясно, что каждый
перечисленный элемент выводится с селектором div[data-cel-widget^="search_result_"]
.
Данный селектор ищет все теги div с атрибутом data-cel-widget
, которые имеют
значение, начинающееся с search_result_
. Аналогичным образом исключаем
селекторы со следующими параметрами:
- total listed items:
div[data-cel-widget^="search_result_"]
- brand:
div[data-cel-widget="search_result_${i}"] .a-size-base-plus.a-color-base
(i обозначает номер узла вtotal listed items
) - product:
div[data-cel-widget="search_result_${i}"] .a-size-base-plus.a-color-base
илиdiv[data-cel-widget="search_result_${i}"] .a-size-medium.a-color-base.a-text-normal
- url:
div[data-cel-widget="search_result_${i}"] a[target="_blank"].a-link-normal
- image:
div[data-cel-widget="search_result_${i}"] .s-image
- price:
div[data-cel-widget="search_result_${i}"] span.a-offscreen
Примечание:
мы ожидаем доступа к селектору именованных элементов div
[data-cel-widget^="search_result_"]
с помощью метода page.waitFor
.
При запуске метода page.evaluate
мы увидим в логе необходимые данные:
Имитируем поведение пользователя
Теперь мы можем перейти на страницу, извлечь необходимые данные и преобразовать их в понятную для нашего API форму.
Но что если, прежде чем извлечь данные, мы должны перейти по нескольким URL? Puppeteer умеет имитировать поведение юзера. Перейдем на домашнюю страницу amazon.in и найдем рубашки. Это приведет нас к странице списка продуктов, а оттуда мы сможем извлечь необходимые данные из DOM. Взглянем на код:
Ждем, пока поле поиска будет доступно, а затем
добавляем searchTerm
, переданный с помощью page.evaluate
. Переходим на страницу
списка продуктов, эмулируя щелчок по кнопке поиска – получаем желанное.
Некоторые нюансы в работе
Есть несколько моментов, с которыми вы можете столкнуться во время работы.
- Некоторые ресурсы могут заблокировать доступ, если заподозрят странную активность. Для рандомизации user-agent в браузере используйте пакет
user-agents
:
- Puppeteer не идеален в вопросе производительности. Повысить эффективность можно за счет троттлинга анимации, ограничения сетевых вызовов и т. д.
- Не забывайте завершать сеанс Puppeteer, закрывая экземпляр браузера с помощью
browser.close
. - Некоторые распространенные операции, такие как
console.log()
не будут работать внутри методов страницы. Контекст страницы/браузера отличается от контекста ноды, в которой работает приложение.
Собираем всё вместе
Автоматизируем навигацию на странице со списком продуктов.
Теперь у вас есть собственный и настраиваемый API для сбора данных. Остается лишь подключить это все к серверной платформе.
Заключение
Мы рассмотрели всего лишь один конкретный случай использования Puppeteer. Для лучшего понимания возможностей инструмента рекомендуем потратить некоторое время на ознакомление с официальной документацией. Многое о библиотеке можно понять из оглавления, содержащего перечень классов и методов.
Комментарии