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 находится в том же домене.
Последний снимок экрана:
Я не автоматизировал часть заполнения реквизитов карты. Я сделаю это вручную ;-)
Полный код доступен как суть здесь.