Puppeteer — это библиотека Node JS, которая предоставляет API для управления браузером Chrome и выполнения почти всех операций, которые разработчик/пользователь может выполнять вручную. Это включает в себя:

  • посещение веб-страницы
  • вход в систему и выполнение действий пользователя
  • взаимодействие с одностраничными приложениями[SPA]
  • Делаем скриншоты
  • Загрузка файлов
  • захват временной шкалы веб-инструментов и т. д.

Это немного отличается от других доступных поисковых роботов, так как это настоящий браузер, только без частей с графическим интерфейсом. Это означает, что сканирование стало намного лучше, и мы можем делать такие вещи, как сохранение в PDF или изображения. Еще одним преимуществом puppeteer является простота использования, синтаксис прост и управляется пользователем, как если бы он был декларативным.

Я хотел показать простой пример прохождения сложного пользовательского пути в SPA при создании полезной утилиты для себя. Итак, я решил написать утилиту для автоматизации процесса бронирования билетов в кино на сайте jazzcinemas (который я регулярно бронирую). Весь процесс бронирования билетов представляет собой хорошее сочетание вариантов использования лотов, с которыми приходится сталкиваться при написании краулера.

Благодаря своим мощным функциям Puppeteer также можно использовать в качестве хорошей утилиты сквозного [E2E] тестирования.

Настройка:

Первым шагом будет установка nodeJS и puppeteer в качестве зависимости от npm. Это все, что нужно. Если вы не хотите загрязнять свою локальную систему, чтобы попробовать ее, возьмите этот образ докера из моего докер-хаба и выполните в нем скрипт.

Посетите веб-сайт и войдите в систему:

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

Бегаем с головой и делаем скриншоты:

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

const browser = await puppeteer.launch( { headless: false, dumpio: true, args: ['--no-sandbox']});

Захват скриншота также очень прост:

await page.screenshot({path: 'ticket.png', fullPage: true});

Пропуск атрибута fullPage приведет к скриншоту текущего видимого раздела.

Внедрение сторонних скриптов:

Поскольку это настоящий браузер, мы можем динамически загружать пользовательские библиотеки/скрипты JS, чтобы улучшить наш опыт сканирования. Например, вместо того, чтобы запрашивать DOM с помощью vanilla JS, можно внедрить jQuery и использовать его.

//Inject custom scripts
await page.addScriptTag({url: 'https://code.jquery.com/jquery-3.2.1.min.js'});

Обнаружение и действия с динамически загружаемым контентом:

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

Чтобы получить доступ к динамическому контенту, puppeteer позволяет нам выполнить внутри действия пользователя с помощью метода Assessment():

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

Действия внутри iframe:

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

Последний снимок экрана:

Я не автоматизировал часть заполнения реквизитов карты. Я сделаю это вручную ;-)

Полный код доступен как суть здесь.