Сигналы автоматизации и согласованность в Playwright
Какие сигналы автоматизации Playwright и Puppeteer показывают странице, почему поздние JavaScript-правки хрупки и как самостоятельно проверить настройку BotBrowser.
BotBrowser Team
Нужна структурированная документация по теме Развертывание?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
Сеансы Playwright и Puppeteer могут показывать странице несколько сигналов, связанных с автоматизацией: флаг navigator.webdriver, привязки фреймворка в контексте страницы, побочные эффекты Chrome DevTools Protocol (CDP) и различия между запусками headless и с окном. При загруженном профиле BotBrowser контролирует navigator.webdriver и, на ENT Tier1, не даёт защищённым событиям консоли и выполнения в CDP менять то, что может наблюдать страница. Ваш собственный тестовый код по-прежнему отвечает за привязки фреймворка, настройки viewport и согласованность прокси, профиля и поведения трафика. Ниже описана каждая категория сигналов, объяснено, почему правки, применённые после загрузки страницы, слабее контроля в самом браузере, и показано, как проверить результат в собственной тестовой среде.
Какие сигналы автоматизации видит страница
Фреймворку автоматизации нужны точки подключения к браузеру. Эти точки находятся в том же браузере, который отображает страницу, поэтому часть из них может прочитать JavaScript, работающий на ней. На практике важны четыре категории, и у каждой свой ответственный, если вам нужна согласованная тестовая среда.
Флаг navigator.webdriver
Спецификация W3C WebDriver определяет navigator.webdriver как способ для страницы узнать, что браузер находится под автоматическим управлением. Он задумывался как механизм прозрачности, поэтому автоматизированный сеанс обычного Chromium, как правило, возвращает true. Это один из самых простых для чтения сигналов, ведь его возвращает одно выражение. Поэтому это и первое значение, которое стоит проверить, если тестовая среда ведёт себя неожиданно.
Привязки фреймворка
Playwright добавляет в контекст страницы вспомогательные имена, например __playwright__binding__ и __pwInitScripts, чтобы фреймворк мог обмениваться данными со страницей. Эти имена существуют из-за того, как фреймворк взаимодействует с браузером. Это требования дизайна, а не дефекты. Puppeteer не добавляет такие же привязки, поэтому его главный вопрос согласованности другой: если остаётся активным viewport по умолчанию, размеры окна перестают совпадать с профилем.
Побочные эффекты CDP
Playwright и Puppeteer управляют Chromium через CDP. Некоторые проверки согласованности во время выполнения могут вывести наличие CDP-соединения из изменений, которые автоматизация способна вызвать в поведении консоли или исключений, например когда клиент включает домены Console или Runtime. Этот сигнал относится к поведению, а не к видимому свойству, поэтому чистая проверка свойств его не исключает.
Из защиты, описанной ниже, следует практический вывод: когда подавление консоли активно, ваш клиент автоматизации не получает пересылаемые сообщения консоли страницы. Командам, которые полагаются на обработчик событий консоли в собственных скриптах, стоит учесть это до первого запуска в рабочей среде.
Различия между headless и запуском с окном
Сеанс headless и сеанс с окном могут отличаться геометрией экрана, списками плагинов и графическим поведением. Профиль задаёт оба режима одни и те же ожидаемые значения, но служба отображения хоста и графический бэкенд всё равно влияют на то, что измеряет страница. Сравнивайте режимы, которые вы действительно используете, в своей среде, а не предполагайте, что они совпадают. Руководство о согласованности профилей между headless и запуском с окном описывает метод проверки для этого случая.
Почему хрупки правки после загрузки страницы
Распространённый подход: плагин сообщества работает внутри страницы и меняет значения после запуска браузера. Он подменяет navigator.webdriver геттером на JavaScript, удаляет имена фреймворка из глобальной области и корректирует другие свойства. У такого подхода есть ограничения, важные для согласованности.
Во-первых, он работает в том же мире JavaScript, что и страница. То, что браузер сообщал до запуска скрипта, заменяется значением, заданным из скрипта, и замена может отличаться по форме от собственной реализации браузера. Свойство, которое браузер никогда не определял, и свойство, удалённое скриптом, не всегда выглядят одинаково для последующего кода.
Во-вторых, правку нужно повторять для каждой новой страницы, фрейма и контекста, и она может не дойти до каждого контекста выполнения. Каждый дополнительный слой нужно синхронизировать после обновления фреймворка или браузера. Когда список правок растёт, риск не только в том, что одна из них не сработает. Сочетание правок может дать сеанс, который уже не ведёт себя как какой-либо настоящий браузер.
В-третьих, правка одного свойства не решает остальные. Изменение строки User-Agent, например, не затрагивает navigator.webdriver, привязки фреймворка или поведение CDP и может создать расхождение между представляемой личностью браузера и средой, которая реально работает.
Некоторые команды отвечают сборкой собственного Chromium без параметров автоматизации. Это убирает категорию сигналов в источнике, но требует поддерживать форк: перебазировать код на каждый выпуск Chrome, разрешать конфликты и мириться с долгими сборками. Для большинства команд такие вложения трудно оправдать по сравнению с поддерживаемым браузером, который документирует, что он контролирует.
Один узкий случай поздней правки остаётся разумным. Очистка через addInitScript двух имён Playwright выполняется до любого скрипта страницы и удаляет только то, что добавил фреймворк. Это небольшой документированный шаг, а не большой слой подмен, и документация BotBrowser сохраняет его в рекомендуемой настройке.
Что BotBrowser документирует для согласованности автоматизации
BotBrowser документирует следующие элементы управления для сценариев автоматизации. В каждой строке указано документированное поведение и уровень, где оно применяется, чтобы вы могли решить, какие из них включить в свою конфигурацию.
| Элемент управления | Документированное поведение | Уровень |
|---|---|---|
Загруженный профиль (--bot-profile) | navigator.webdriver контролируется автоматически; дополнительный флаг не нужен | Core |
--bot-disable-console-message | Не даёт защищённым событиям консоли и выполнения менять поведение, видимое странице, пока подключён CDP; включён по умолчанию | ENT Tier1 |
--bot-disable-debugger | Игнорирует инструкции JavaScript debugger, чтобы выполнение не останавливалось | Core |
--bot-always-active | Сохраняет окна и вкладки активными, когда у них нет фокуса; включён по умолчанию | PRO |
--bot-port-protection | Не даёт удалённым страницам определять, какие службы работают на портах localhost | PRO |
--bot-script | Запускает ваш скрипт в привилегированном изолированном контексте страницы без внешних привязок фреймворка и отдельного клиента CDP | Core |
Флаг консоли требует точного прочтения. Он защищает пути событий консоли и выполнения. Он не отключает домен CDP Runtime, поэтому обычное вычисление выражений и обработка исключений остаются доступными вашей автоматизации. Диагностические сеансы, где защита намеренно выключена через --bot-disable-console-message=false, меняют поведение CDP, поэтому считайте их отдельным запуском проверки совместимости и не сравнивайте их результаты с рабочими.
--bot-script даёт наименьший след фреймворка, потому что не требует ни Playwright, ни Puppeteer. Если вашу задачу можно выразить скриптом, работающим внутри браузера, привязки фреймворка не появляются вовсе. Используйте --bot-title, когда заголовок страницы показывает имя расширения.
Настройка Playwright и Puppeteer
Устанавливайте playwright-core или puppeteer-core, а не полные пакеты. Полные пакеты загружают собственный Chromium, который не нужен, когда вы запускаете BotBrowser по пути. Храните профиль, путь к бинарному файлу и прокси в переменных окружения или конфигурации, чтобы каждый запуск фиксировал одни и те же входные данные.
import { chromium } from 'playwright-core';
const browser = await chromium.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
args: [
'--disable-audio-output',
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
'--proxy-server=socks5://user:pass@proxy.example.com:1080',
],
});
const page = await browser.newPage();
await page.addInitScript(() => {
delete window.__playwright__binding__;
delete window.__pwInitScripts;
});
await page.goto('https://example.com');
Сначала создайте страницу, зарегистрируйте очистку и только потом переходите по адресу. Скрипт инициализации должен быть на месте до первого goto, иначе страница может выполниться раньше, чем имена будут удалены. Не задавайте также параметры viewport в Playwright, потому что размеры должен определять профиль.
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
defaultViewport: null,
args: [
'--disable-audio-output',
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
'--proxy-server=socks5://user:pass@proxy.example.com:1080',
],
});
const page = await browser.newPage();
await page.goto('https://example.com');
В Puppeteer важна строка defaultViewport: null. Без неё Puppeteer применяет собственный viewport и переопределяет размеры экрана из профиля, а несовпадающий viewport становится проблемой согласованности, созданной вами самими.
Задавайте прокси через --proxy-server (или параметр прокси для отдельного контекста), а не через настройки прокси, существующие только во фреймворке. BotBrowser согласует часовой пояс, локаль и языки с регионом прокси только тогда, когда сам маршрутизирует трафик. Ручное значение --bot-timezone, --bot-locale или --bot-languages заменяет это соответствие, а значения auto продолжают следовать за прокси. Если вы загружаете профили из каталога через --bot-profile-dir, BotBrowser выбирает один профиль при каждом запуске, а параметр каталога нельзя сочетать с --bot-profile (если указаны оба, приоритет у каталога).
На сервере Linux BotBrowser по-прежнему нужен виртуальный дисплей, например Xvfb, даже при запуске с --headless, и переменная DISPLAY должна быть задана для каждого запуска BotBrowser. Для долгих задач полезны два флага PRO. --bot-always-active включён по умолчанию и сохраняет окна и вкладки активными, когда у них нет фокуса, что соответствует поведению основного браузера. --bot-port-protection не даёт удалённым страницам узнавать, какие службы работают на локальных портах, например удалённый рабочий стол или серверы разработки. Ни один из флагов не меняет способ подключения Playwright или Puppeteer, поэтому их можно добавить в аргументы запуска после успешных базовых проверок.
Проверка настройки в собственной тестовой среде
Проверка представляет собой регрессионный контроль вашей собственной конфигурации. Она показывает, соответствует ли запуск документированному поведению сегодня и соответствует ли после обновления BotBrowser, профиля или фреймворка. Она не предсказывает, как какой-либо сторонний сайт отнесётся к сеансу.
Начните с записи входных данных: версия BotBrowser, файл профиля, аргументы запуска, версия фреймворка, режим headless или с окном и регион прокси. Без этой записи более позднее расхождение нельзя связать с конкретным изменением.
Затем на странице, которую вы контролируете, прочитайте небольшой набор значений и сравните их с тем, что должны давать профиль и ваши параметры запуска:
navigator.webdriverдолжен бытьfalseпосле загрузки профиля.- Два имени привязок Playwright должны отсутствовать, если скрипт инициализации выполнился до перехода.
- Размеры окна и экрана должны совпадать с профилем, а записи языков и плагинов должны соответствовать ожидаемой локали.
- Поведение консоли должно соответствовать вашему замыслу: при значениях ENT Tier1 по умолчанию обработчик консоли вашего клиента не должен получать ничего от страницы.
- Часовой пояс и языки должны следовать за регионом прокси или за вашими явными значениями.
Когда значение отличается, документация указывает конкретную причину для каждого случая:
| Наблюдение | Вероятная причина | Что изменить |
|---|---|---|
navigator.webdriver возвращает true | Профиль не загрузился | Проверьте путь и файл --bot-profile |
| Имена привязок Playwright всё ещё есть | Скрипт инициализации выполнился слишком поздно | Зарегистрируйте addInitScript до первого goto |
| События консоли всё ещё доходят до клиента | Подавление выключено или уровень его не включает | Проверьте значение флага и уровень подписки |
| Viewport не совпадает с профилем | Действует переопределение viewport из фреймворка | Используйте defaultViewport: null в Puppeteer и не задавайте параметры viewport в Playwright |
| Часовой пояс не совпадает с регионом прокси | Прокси задан только через параметры фреймворка | Передавайте прокси через --proxy-server или прокси отдельного контекста |
Страница, которую вы контролируете, может служить вторым мнением о том же сеансе. Читайте её результат как сведения о вашей собственной среде, а не как вердикт третьей стороны. Замечания, указывающие на расхождение между профилем, прокси и локалью, стоит исправлять, даже если ни один сайт никогда не пожалуется.
В конвейере непрерывной интеграции превратите список в проверки, которые останавливают сборку при изменении ожидаемого значения. Запускайте их в том же режиме, что и рабочая задача. Если вы используете и задачи headless, и задачи с окном, запускайте оба варианта. Храните запись версий рядом с результатом, чтобы сбой после обновления легко связывался с компонентом, который изменился.
Разбор неудачного запуска
Допустим, ночная задача начала сообщать, что список языков на вашей тестовой странице больше не совпадает с локалью профиля. Начните с записи, а не с флагов. Сравните версию BotBrowser, файл профиля, аргументы запуска и регион прокси с последним успешным запуском. В этом примере изменился только регион прокси, потому что команда перенесла задачу в другое место выхода.
Следующий шаг объясняет документация. Значения auto следуют за прокси, поэтому список языков изменился вместе с регионом. Если команде нужна фиксированная локаль независимо от места выхода, она явно задаёт --bot-locale или --bot-languages и оставляет часовой пояс в значении auto. После этого запуск повторяет те же пять проверок, и запись обновляется. Итогом становится задокументированное решение о том, какие значения следуют за прокси, а какие закреплены, а не сюрприз, обнаруженный позже.
Согласованность прокси, профиля и трафика
Сигналы автоматизации составляют лишь часть согласованного сеанса. Профиль Chrome для Windows в сочетании с прокси из одной страны и локалью из другой даёт расхождение, если не зафиксировать локаль или не сменить маршрут. Решите, какие атрибуты должны следовать за маршрутом, а какие оставаться фиксированными, запишите это решение и проверяйте его той же процедурой, что и navigator.webdriver.
Поведение трафика входит в ту же проверку. Скрипт, который открывает много страниц в темпе, недоступном человеку, или повторяет одинаковую навигацию в жёстком ритме, создаёт шаблон поведения, который не изменить настройкой браузера. BotBrowser не заменяет эту дисциплину. Держите объём запросов, ритм и использование учётных записей в рамках правил сайтов, с которыми вы работаете, и запускайте только ту автоматизацию, на которую у вас есть разрешение.
Наконец, используйте больше одного профиля, когда задача требует раздельных сред. Повторное использование одного профиля для всех экземпляров означает, что все экземпляры сообщают одну и ту же среду. --bot-profile-dir выбирает один файл из каталога при каждом запуске, что даёт каждому запуску другой профиль без дополнительного кода, и при этом вы можете записывать, какой файл загрузил конкретный запуск.
Ограничения, Selenium и практические вопросы
На ваших собственных тестовых страницах Playwright или Puppeteer BotBrowser автоматически контролирует navigator.webdriver после загрузки профиля, а с флагом --bot-disable-console-message (ENT Tier1, включён по умолчанию) не даёт защищённым событиям консоли и runtime в CDP менять то, что может наблюдать страница, поэтому вы можете сами проверить эти сигналы автоматизации с помощью проверок выше. Задокументированное поведение описано в разделе согласованность автоматизации. Ограничения заданы явно: BotBrowser не может гарантировать, как сторонний сайт классифицирует сеанс, не отключает домен CDP Runtime, не удаляет за вас привязки фреймворка (сохраните очистку через addInitScript) и не заменяет согласованные прокси, профиль и поведение трафика.
Работает ли BotBrowser с Selenium? Документированные конфигурации используют Playwright и Puppeteer. Selenium взаимодействует через протокол WebDriver, который может раскрывать дополнительные сигналы вне описанных здесь защит CDP. BotBrowser по-прежнему контролирует navigator.webdriver при загруженном профиле, но защита консоли и выполнения ограничена путями CDP.
Нужен ли дополнительный плагин правок? Документация не описывает такой плагин как часть рекомендуемой настройки. Плагин, подменяющий те же свойства, добавляет второй источник значений, и это повод сначала проверить работу без него. Добавляйте его только тогда, когда остаётся конкретный подтверждённый пробел.
Меняет ли --bot-disable-debugger отладку? Да. Инструкции debugger в JavaScript страницы игнорируются, поэтому выполнение на них не останавливается. Не включайте флаг в сеансе, где нужна такая пауза, и используйте его для запусков без присмотра.
Что делать, если вывод консоли нужен в рабочей среде? Ведите журнал на уровне приложения, в файлах или внешней службе, вместо пересылки консоли через CDP. Для краткой отладки задайте --bot-disable-console-message=false в отдельном сеансе.
Как сохранять стабильные результаты между обновлениями? Храните бинарный файл BotBrowser, профиль и версию фреймворка в одной записи о выпуске. Повторяйте проверки выше после изменения любого из них. При каждом обновлении просматривайте документацию по используемым флагам, потому что значения по умолчанию и уровни могут меняться между выпусками.
Руководства по началу работы: Начало работы с Playwright и Начало работы с Puppeteer. Об организации профилей: Управление профилями.
Источники
Похожие статьи
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.