Що таке Puppeteer?
Puppeteer — це бібліотека Node, яка пропонує високорівневий API для контролю Chrome чи Chromium за допомогою протоколу DevTools. Puppeteer стандартно працює у headless-режимі, однак бібліотеку можна налаштувати для запуску в повноцінному (non-headless) Chrome чи Chromium. — github.com/puppeteer/puppeteer
Puppeteer автоматизує рутинну роботу, яку ви час від часу виконуєте у браузері. З цією бібліотекою можна контролювати будь-що у браузері: від простої навігації до аудиту вебсайту з Lighthouse.
Перш ніж перейдемо до практики, розглянемо такий приклад скрипту Puppeteer:
Автор посібника проходить курс голландської мови, де доводиться працювати з безліччю слів та діалогів. Створення флеш-карток та імпорт великої кількості слів та звуків — не надто легка та цікава робота. Однак погляньте, як швидко з цим справляється автоматизований скрипт. До того ж він уникає помилок, які може зробити людина.
Написати скрипт для Puppeteer не складно, головне — пам'ятати про деякі основні правила.
Правило №1
Всі методи в Puppeteer асинхронні, тож не забувайте використовувати await
.
Правило №2
У скрипті вам зазвичай доведеться змушувати Puppeteer очікувати на щось: запит, відповідь з бекенду, елемент тощо.
Правило №3
Пишіть скрипт послідовно. Уявіть, що вам потрібен скрипт, який щось гуглитиме. Як ви це зробите?
- Ви відкриєте нову вкладку.
- Перейдете на Google.com.
- Клікнете на пошукову стрічку.
- Введете щось.
- Клікнете на кнопку пошуку.
Puppeteer підтримує декілька API для сторінки, клавіатури, мишки. Описану послідовність дій можна легко емулювати за допомогою бібліотеки.
Правило №4
Ви не можете клікати на невидимий елемент. Уявіть меню з декількома пунктами. Спершу вам треба відкрити список, а потім вже обрати необхідний пункт.
Правило №5
Для деяких сторінок запрограмовано певні події (наприклад події jQuery). Якщо вам потрібно, аби такий код виконався, доведеться зробити це за допомогою JS.
Правило №6
Якщо ви не знайомі з селекторами в CSS, надолужте це.
Правило №7
Коли ви переходите на сторінку на зразок example.com/users/, не забувайте про /
в кінці.
Ми поговорили про базові теоретичні правила, тепер застосуймо їх на практиці.
Розігрів
- Встановіть NodeJS 10.x або вище.
- Встановіть Yarn Package Manager.
Тепер виконайте такі команди у терміналі:
mkdir hello_puppeteer
cd hello_puppeteer
yarn init
yarn add puppeteer
Остання команда триватиме певний час, тому що встановлюється Puppeteer та всі потрібні залежності (на зразок Chromium).
Створіть новий js
-файл та назвіть його google.js
, а потім додайте туди цей код:
const puppeteer = require("puppeteer");
(async () => {
// запускаємо браузер
const browser = await puppeteer.launch({
headless: false,
// devtools: false,
// args: ["--start-maximized"]
});
// створюємо нову вкладку
const page = await browser.newPage();
})();
- Метод
puppeteer.laucnh
запускає новий екземпляр браузера Chromium. Якщо ви поглянете на код, то помітите там прапорheadless: false
. Так ми побачимо, що відбувається під капотом. - Метод
browser.newPage
створює нову вкладку в браузері. - Автор огорнув блок коду в асинхронну функцію, адже всі методи Puppeteer асинхронні.
Спробуйте запустити скрипт командою node google.js
— в терміналі ви побачите такий результат:
Далі нам потрібно перейти на Google.com. Для цього додамо після const page = ...
цей код:
// переходимо на google.com
await page.goto('https://web.archive.org/web/20230322034327/https://google.com');
Тепер ми маємо ввести пошуковий запит на Google.com. Спершу треба дослідити пошукову стрічку за допомогою Web Developer Tools (клік правою кнопкою на пошукову стрічку, виберіть опцію «Дослідити елемент»).
Спочатку необхідно знайти статичний CSS-селектор, аби працювати з ним у Puppeteer. Стрічка вводу має декілька атрибутів, але ми звернемо увагу на ці:
-
class
: на жаль, він динамічний, і ми не можемо покладатися на нього. -
name
: значення цього атрибута унікальне для цілої сторінки. Тому обираємо саме його.
Спробуйте знайти елемент за CSS-селектором безпосередньо в інструментах розробника, на вкладці з консоллю. Елементи можна протестувати за допомогою document.querySelector
, document.querySelectorAll
.
Ми обрали CSS-селектор input[name=q]
— і він працює чудово. Саме час ввести запит для пошуку.
await page.focus('input[name=q]');
/* або ви можете: спершу знайти елемент, а потім зробити на ньому фокус
const searchInput = await page.$('input[name=q]');
await searchInput.focus();
*/
Для API сторінки символ $
працює подібно до documnet.querySelector
, а $$
— подібно до document.querySelectorAll
.
Аби Puppeeter міг ввести щось в поле вводу, необхідно зробити на ньому фокус. Для цього існує два API. Обидва дають однаковий результат, однак застосовуються в різних ситуаціях.
В поле вводу можна легко щось ввести, використовуючи keyboard
API.
await page.keyboard.type('Puppeteer');
Далі нас цікавить, як отримати результати пошуку. Зазвичай користувачі тиснуть на Enter або клікають на кнопку Google Search. Аби відтворити такий функціонал, ми можемо:
// натиснути клавішу Enter на клавіатурі
await page.keyboard.press("Enter");
// або спершу сфокусувати кнопку пошуку, а потім клікнути на неї
// const searchButton = await page.$('input[name=btnK]');
// await searchButton.click();
Ми ознайомилися з базовим функціоналом, однак на цьому можливості Puppeteer не закінчуються.
Попросіть Puppeteer почекати на щось
Розглянемо такі сценарії:
- Ajax-запит надсилається після кліку на кнопку.
Приклад завантаження файлу для file-input
:
const fileInput= await page.$('input[type=file]');
const uploadButton = await page.$('#upload-btn');
await fileInput.uploadFile("d:/image.jpg");
await uploadButton.click();
// тепер почекаємо на результат статусу завантаження
await page.waitForResponse('https://web.archive.org/web/20230322034327/https://example.com/services/upload/');
// знайдемо динамічно згенероване посилання після ajax завантаження
const fileUrlElement = await page.$('a.file-url');
- Заждемо декілька секунд.
await page.waitFor(1000); // у мілісекундах
- Очікуємо на навігацію сторінки.
await page.waitForNavigation();
- Почекаємо, поки певний CSS-селектор буде показаний на сторінці.
await page.waitForSelector('css selector');
Виконання скриптів у браузері
Іноді трапляється, що після завантаження файлу методом uploadFile
сторінка не виконує Ajax-завантаження. В такому разі потрібно застосувати jQuery-код, який виконає цю роботу.
const input = await page.$('input[type=file]');
await input.uploadFile(fileToUpload);
await page.evaluate(
element => $(element).trigger("custom_event"),
input
);
У прикладі вище $(element).trigger("...")
— це JS-код, який виконається в браузері (а не в скрипті Puppeteer).
Більше можливостей
У першому прикладі ми використали прапор headless: false
, аби побачити, як все відбувається під капотом. Зазвичай краще використовувати headless-режим, адже так скрипти та браузер запускаються фоново і ви не відволікаєтесь на вкладки та вікна.
Але як побачити результат, запустивши скрипт у режимі headless? Як щодо скріншотів?
await page.screenShot({path: 'my-result.png', fullPage: true})
На початку матеріалу автор продемонстрував роботу власного скрипту з імпорту карток. Повний його код можна знайти за посиланням.
Більше прикладів
Якщо ви хочете дізнатись більше про можливості Puppeteer, зверніть увагу на цей репозиторій. Інші бібліотеки також покладаються на Puppeteer, наприклад генератор ресурсів для PWA.
Ще немає коментарів