← Browser Run / browser-run
Puppeteer
Puppeteer ↗ одна из самых популярных библиотек, которая скрывает от разработчиков низкоуровневый протокол DevTools и предоставляет высокоуровневый API для удобной работы с Chrome/Chromium и автоматизации сессий браузера. Puppeteer используют для таких задач, как создание скриншотов, обход страниц и тестирование веб-приложений.
Обычно Puppeteer подключается к локальному браузеру Chrome или Chromium через порт DevTools. См. документацию Puppeteer API на Puppeteer.connect() метод ↗, где это описано подробнее.
Команда Workers создала форк версии Puppeteer и модифицировала её для подключения к API Workers Browser Run. После подключения разработчики могут использовать весь Puppeteer API ↗ как и при стандартной настройке.
Наша версия имеет открытый исходный код, её можно найти в форк Puppeteer от Cloudflare ↗. npm можно установить из npmjs ↗ как @cloudflare/puppeteer ↗:
npm i -D @cloudflare/puppeteerИспользуйте Puppeteer в Worker
После того как привязка browser настроен и @cloudflare/puppeteer библиотека установлена, Puppeteer можно использовать в Worker:
import puppeteer from "@cloudflare/puppeteer";
export default {
async fetch(request, env) {
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto("https://example.com");
const metrics = await page.metrics();
await browser.close();
return Response.json(metrics);
},
};import puppeteer from "@cloudflare/puppeteer";
interface Env {
MYBROWSER: Fetcher;
}
export default {
async fetch(request, env): Promise<Response> {
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto("https://example.com");
const metrics = await page.metrics();
await browser.close();
return Response.json(metrics);
},
} satisfies ExportedHandler<Env>;Этот скрипт запускает ↗ env.MYBROWSER браузер, открывает новая страница ↗, переходит на ↗ https://example.com/ ↗, получает загрузку страницы метрики ↗, закрывает ↗ браузер и выводит метрики в формате JSON.
Keep Alive
Если пользователи не указывают browser.close() то браузер останется открытым, готовым к повторному подключению, а также повторно используется но по умолчанию она автоматически закрывается через 1 минуту бездействия. Пользователи могут по желанию продлить время простоя до 10 минут с помощью keep_alive параметр, заданный в миллисекундах:
const browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 });При таком подходе браузер остаётся открытым до 10 минут, даже если он неактивен.
Задайте собственный User-Agent
Чтобы указать собственный user agent в Puppeteer, используйте page.setUserAgent() метод. Это полезно, если целевой сайт отдаёт разный контент в зависимости от user agent.
await page.setUserAgent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
);Локальная отладка в headful-режиме (экспериментально)
При локальной разработке с wrangler dev или vite dev, Chrome по умолчанию запускается в режиме headless. Чтобы запустить Chrome в видимом режиме (headful), задайте X_BROWSER_HEADFUL переменную окружения:
X_BROWSER_HEADFUL=true npx wrangler devИли с помощью Cloudflare Vite plugin:
X_BROWSER_HEADFUL=true npx vite devЭто открывает окно браузера, чтобы вы могли наблюдать за работой автоматизации Puppeteer в режиме реального времени, что упрощает отладку навигации, выбора элементов и взаимодействия со страницей.
Выбор элемента
Puppeteer предоставляет несколько способов выбора элементов на странице. CSS-селекторы работают как обычно, но XPath-селекторы не поддерживаются из-за ограничений безопасности среды выполнения Workers.
Вместо селекторов Xpath можно использовать селекторы CSS или page.evaluate() чтобы выполнять XPath-запросы в контексте браузера:
const innerHtml = await page.evaluate(() => {
return (
// @ts-ignore this runs on browser context
new XPathEvaluator()
.createExpression("/html/body/div/h1")
// @ts-ignore this runs on browser context
.evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue
.innerHTML
);
});Управление сессиями
Чтобы упростить управление сессиями браузера, мы добавили новые методы в puppeteer:
Список открытых сеансов
puppeteer.sessions() выводит список текущих выполняющихся сессий. Результат будет выглядеть примерно так:
[
{
"connectionId": "2a2246fa-e234-4dc1-8433-87e6cee80145",
"connectionStartTime": 1711621704607,
"sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc",
"startTime": 1711621703708
},
{
"sessionId": "565e05fb-4d2a-402b-869b-5b65b1381db7",
"startTime": 1711621703808
}
]Обратите внимание, что сессия 478f4d7d-e943-40f6-a414-837d3736a1dc есть активное подключение Worker (connectionId=2a2246fa-e234-4dc1-8433-87e6cee80145), в то время как сеанс 565e05fb-4d2a-402b-869b-5b65b1381db7 бесплатен. Пока соединение активно, другие Worker не смогут подключиться к этой сессии.
Список последних сеансов
puppeteer.history() выводит список недавних сессий, как открытых, так и закрытых. Это удобно, чтобы оценить текущий объём использования.
[
{
"closeReason": 2,
"closeReasonText": "BrowserIdle",
"endTime": 1711621769485,
"sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc",
"startTime": 1711621703708
},
{
"closeReason": 1,
"closeReasonText": "NormalClosure",
"endTime": 1711123501771,
"sessionId": "2be00a21-9fb6-4bb2-9861-8cd48e40e771",
"startTime": 1711123430918
}
]Сессия 2be00a21-9fb6-4bb2-9861-8cd48e40e771 была закрыта явным образом с помощью browser.close() клиентом, тогда как сессия 478f4d7d-e943-40f6-a414-837d3736a1dc была закрыта из-за достижения максимального времени простоя (см. ограничения).
Эту информацию можно также посмотреть в панели управления, хотя и с небольшой задержкой.
Действующие лимиты
puppeteer.limits() выводит ваши текущие лимиты:
{
"activeSessions": [
{ "id": "478f4d7d-e943-40f6-a414-837d3736a1dc" },
{ "id": "565e05fb-4d2a-402b-869b-5b65b1381db7" }
],
"allowedBrowserAcquisitions": 1,
"maxConcurrentSessions": 2,
"timeUntilNextAllowedBrowserAcquisition": 0
}activeSessionsвыводит идентификаторы текущих открытых сессийmaxConcurrentSessionsопределяет, сколько браузеров может быть открыто одновременноallowedBrowserAcquisitionsуказывает, можно ли открыть новую сессию браузера согласно ограничения на местеtimeUntilNextAllowedBrowserAcquisitionопределяет время ожидания перед запуском нового браузера.
Puppeteer API
Полный API Puppeteer можно найти в форк Puppeteer от Cloudflare ↗.