Назад к блогу
Развертывание

Сигналы безголового и обычного браузера: метод сравнения

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

BotBrowser Team

Сигналы безголового и обычного браузера: метод сравнения
Документация

Нужна структурированная документация по теме Развертывание?

Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.

Команды спрашивают, «видит» ли страница безголовый браузер, и честный ответ в том, что она видит набор значений, часть которых различается между режимами, а часть нет. Эта статья даёт метод, чтобы выяснить, какие именно, и стоит рядом с руководством по защите отпечатка при сборе данных: то руководство описывает, что должна сохранять согласованным разрешённая сессия сбора, а это описывает, как измерить разницу между режимами, прежде чем доверять любому из них.

BotBrowser может запускать объявленный профиль в обычном и безголовом режимах и держать видимые значения браузера согласованными с этим профилем, что делает возможным сравнение трёх сессий на собственной фикстуре; он не может сделать безголовый браузер идентичным обычному на каждой поверхности, не предсказывает решение стороннего сайта и не заменяет проверку реальных страниц, которые посещает ваш процесс.

Сравнение сигналов безголового и обычного браузера

Кратко

  • Сравнивайте три сессии, а не две: обычную, безголовую и профильную в том режиме, который вы развёртываете.
  • Используйте одну версию фикстуры и записывайте одни и те же поля в каждой.
  • Сравнивайте записи по полям и относите каждое расхождение к ожидаемым или необъяснённым.
  • Необъяснённое расхождение это находка, которую нужно объяснить, а не дефект, который нужно замаскировать.

Содержание

Начните с собственной фикстуры

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

Пишите фикстуру так, чтобы она сообщала значения, а не вердикты. Страница, печатающая «безголовый режим обнаружен», это страница, чью логику пришлось бы проверять прежде, чем ей верить. Страница, сообщающая navigator.userAgent, navigator.platform, screen.width, screen.height, devicePixelRatio, navigator.hardwareConcurrency, Intl.DateTimeFormat().resolvedOptions().timeZone и наличие нескольких конструкторов API, даёт значения, которые можно сравнить, не веря ни одному из них.

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

Включите хотя бы одно поле, которое должно различаться. Сравнение, где всё совпадает, может означать, что режимы согласны, а может означать, что фикстура перестала что-то сообщать. Ожидаемое расхождение служит контролем: если оно исчезло, фикстура изменилась.

Записывайте одни и те же поля три раза

Первая сессия обычная, без профиля. Это эталон, который читатель узнает: обычное окно браузера на обычном дисплее. Вторая безголовая, тоже без профиля, поэтому единственный изменённый вход это режим. Третья это конфигурация развёртывания: профиль, который вы действительно поставляете, в режиме, в котором вы действительно работаете.

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

Записывайте поля как плоский объект, чтобы инструмент сравнения мог сопоставлять их, не зная структуры. Внутри поля вложенные объекты допустимы, но верхний уровень должен быть списком имён и значений, который покажет простое построчное сравнение. Запись из двадцати плоских полей сравнивать легче, чем запись из четырёх вложенных.

Храните вывод каждой сессии отдельно и называйте по режиму. headed.json, headless.json и profile.json делают сравнение трёх сессий очевидным и позволяют перезапустить одну сессию, не перезапуская все три.

Классифицируйте каждое расхождение

Расхождение между обычным и безголовым режимом не обязательно проблема. Одни ожидаемы, потому что режим меняет работу браузера, другие ожидаемы, потому что профиль развёртывания объявляет значение, которого не было ни в одной из двух сессий по умолчанию.

Пользовательский агент (navigator.userAgent) это самое очевидное ожидаемое расхождение. Безголовый браузер часто сообщает признак безголового режима, а профиль может объявить другой. Это декларация, а не утечка, и запись должна указывать, какая сессия её объявила.

Размеры экрана (screen.width и screen.height) могут различаться, потому что виртуальный дисплей безголовой сессии это не физический дисплей обычной. Профиль, объявляющий размер экрана, меняет его снова. Интересно не то, различаются ли они, а согласован ли объявленный развёртыванием размер с другими зависящими от него значениями, например размером окна и областью просмотра.

Соотношение пикселей (devicePixelRatio) часто различается по той же причине. Безголовая сессия с виртуальным дисплеем по умолчанию может сообщать одно соотношение, обычная сессия соотношение физического дисплея, а профиль объявить третье. Записывайте соотношение и получающуюся из него область просмотра вместе, потому что соотношение без области просмотра не описывает, что измерила страница.

Поверхности времени и отрисовки чаще всего различаются по настоящим причинам. У безголовой сессии может не быть GPU, композиция может идти иначе, а вывод canvas отличаться. Именно эти расхождения стоит изучать, потому что именно по ним страница может отличить режимы, даже когда все объявленные значения совпадают.

Расхождение, появляющееся только в профильной сессии, обычно означает, что декларация вступила в силу. Сравнивайте его с файлом профиля, а не с обычной сессией, и записывайте, совпадают ли объявленное и наблюдаемое значения. Эта проверка и есть смысл третьей сессии.

Расхождение, появившееся лишь в одном запуске одного режима, не ожидаемое и не расхождение режимов. Это колебание между запусками, и сравнение его с двумя другими сессиями введёт в заблуждение. Запустите ту же сессию дважды до классификации и считайте расхождение, появившееся один раз, шумом, пока оно не повторится.

Делайте сравнение запускаемым

Сравнение, живущее в одноразовом скрипте, это сравнение, которое никто не перезапускает. Поставьте три сессии за одну команду, например npm run compare:modes, записывайте три записи в фиксированный каталог и пусть сравнение будет командой, а не суждением. Когда обновление браузера что-то меняет, сравнение трёх сессий показывает это одной строкой на поле.

Храните фикстуру и записи в системе контроля версий, указывая версию фикстуры в имени файла. Тогда поздний читатель видит, какие поля сравнивались в какой момент, а история постоянно меняющегося поля видна без вопросов к кому-либо.

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

Не превращайте сравнение в проверку «прошло или нет» на совпадение режимов. Режимам разрешено различаться; такая проверка должна ловить поле, которое незаметно перестало записываться, или объявленное значение, которое перестало появляться. Проверка, падающая при каждом расхождении обычного и безголового режимов, будет проигнорирована за месяц.

Сохраняйте честность сравнения

Решите, какие выводы оно допускает

Сравнение трёх сессий отвечает на узкий вопрос: для этих полей, на этой фикстуре, в этом пакете браузера, что различается между режимами и что различается после применения профиля. Оно не отвечает, примет ли сайт безголовую сессию, обнаруживаема ли безголовая сессия вообще и безопаснее ли обычная. Эти вопросы касаются логики самого сайта, политики учётных записей и правил риска, которых фикстура не видит.

Формулируйте вывод в этой узкой форме. «На fixture@v4 с пакетом 155 пользовательский агент и размер экрана различаются между обычным и безголовым режимами до применения профиля и совпадают с объявленными значениями профиля после» это вывод, который запись поддерживает. «Безголовый режим подходит» нет, и он провоцирует решение, которое данные не выдержат.

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

Делитесь расхождением, а не выводом. Коллега, изучающий изменившееся поле, сам решит, что оно значит для его процесса; коллега, получивший вердикт, вынужден принять его на веру. Три записи и расхождение в одну строку это артефакт, который стоит хранить.

Обновляйте вывод при смене пакета или формата профиля. Вывод, написанный для одной версии пакета, описывает эту версию, а поздний читатель, найдя его при другой версии, применит его неверно. Датируйте вывод и называйте входы, к которым он относится.

Обращайтесь осторожно с легко ошибочными полями

Некоторые поля выглядят как сигналы браузера, но на самом деле это значения запроса или среды, и сравнение их между режимами без понимания этого расходует сравнение впустую. HTTP-заголовки, которые отправляет сессия, собираются из нескольких источников, и заголовок пользовательского агента может отличаться от navigator.userAgent в зависимости от драйвера и параметров запуска.

Записывайте и значение, видимое странице, и заголовок запроса, когда они должны совпадать. Несовпадение между ними это реальная находка, и она незаметна, если фикстура сообщает только значение страницы. Фиксируйте заголовок запроса в тот же момент, что и значение страницы, чтобы они описывали одну навигацию.

Локаль и часовой пояс заслуживают того же подхода. Intl.DateTimeFormat().resolvedOptions().locale, Intl.DateTimeFormat().resolvedOptions().timeZone и navigator.language это отдельные значения, которые могут расходиться, а безголовая сессия на сервере с другой системной локалью способна дать сочетание, которого обычная сессия никогда не показывает. Записывайте все три, а не одно.

Измерения canvas и шрифтов требуют внимания, потому что зависят от отрисовки, а именно здесь безголовая сессия вправе отличаться. Записывайте измерение и путь отрисовки вместе и считайте расхождение ожидаемым, когда путь различается, и достойным изучения, когда нет. Руководство по путям отрисовки canvas объясняет, почему два программных пути могут дать разный вывод на одной машине.

Сделайте сравнение читаемым

Сравнение двух записей JSON читаемо, когда у записей общая плоская форма и короткие значения. Форматируйте записи с отсортированными ключами, одним полем на строку и вложенностью не глубже одного уровня. Достаточно инструмента, который печатает <field>: <headed> -> <headless> для каждого изменившегося поля; собственный формат отчёта не нужен.

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

Ведите короткий журнал полей рядом с фикстурой. Когда поле добавлено, запишите дату и причину; когда удалено, запишите это тоже, потому что удалённое поле выглядит так же, как поле, переставшее сообщаться. Журнал отличает намеренное изменение от тихого.

Запускайте сравнение в непрерывной интеграции и роняйте его только когда поле исчезло или объявленное значение больше не совпадает с профилем. Сравнение, падающее при каждом расхождении режимов, отключат, а отключённое сравнение хуже того, которое сообщает и даёт прочитать человеку.

Проверяйте перед выпуском

Проверка выпуска спрашивает, сообщает ли развёртывание по-прежнему то, что объявило. Сравнение трёх сессий отвечает прямо: значения профильной сессии против файла профиля и две сессии по умолчанию против собственной базовой линии. Запускайте его как часть проверки выпуска, а не после инцидента, и храните результат рядом с profile.json.

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

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

Сравнивайте развёртывание, а не только режимы

Сравнение трёх сессий показывает, что различается между режимами. Оно не показывает, согласовано ли само развёртывание внутри себя, а это другой вопрос с другой записью. Профильная сессия может совпадать с объявленным пользовательским агентом и при этом объявлять размер экрана, не согласованный с размером окна, а ни расхождение, ни проверка одного поля этого не поймают.

Добавьте проход согласованности, который сравнивает поля профильной сессии между собой, а не с другими сессиями. Область просмотра (window.innerWidth и window.innerHeight) должна помещаться в объявленный экран; часовой пояс, локаль и язык должны описывать один регион; платформа должна быть совместима с пользовательским агентом. Каждое из этих правил формулируется одной строкой и проверяется в том же запуске фикстуры.

Храните правила рядом с фикстурой и давайте каждому имя. Когда правило нарушено, запись говорит, какое именно, а не только какое поле изменилось, и читателю не нужно заново открывать связь. Правила также переживают переименование поля, чего не делает жёстко заданное сравнение.

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

Сообщайте о нарушениях правил отдельно от расхождений режимов. Расхождение режимов ожидаемо и информативно; нарушение правила это проблема конфигурации, за которую отвечает развёртывание. Смешивание их в одном списке делает ожидаемые расхождения шумными, а проблемы конфигурации легко пропустить.

Как использовать сравнение, когда приходит сообщение

Сообщение, что сайт «обнаруживает автоматизацию», приходит как фраза, а не как запись. Сравнение превращает фразу в вопрос: какое поле изменилось с последнего заведомо хорошего сравнения и изменилось ли оно в режиме, который использует процесс.

Сначала запросите идентификатор запуска (runId) и сравнение того же развёртывания. Без них первый час уходит на выяснение, что вообще работало, а эту информацию сравнение уже хранит. С ними проверяющий сразу переходит к изменившемуся полю.

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

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

Делайте сравнение достаточно дешёвым, чтобы запускать по требованию. Сравнение, требующее целого дня подготовки, запускают после инцидента, а не во время, и инцидент заканчивается раньше, чем появляются записи.

Практический итог

Безголовый и обычный браузеры различаются ожидаемыми способами, способами, объявленными профилем, и способами, которые стоит изучать. Запустите три сессии на одной собственной фикстуре, записывайте одни и те же плоские поля, классифицируйте каждое расхождение и делайте сравнение запускаемым. Используйте его вместе с руководством по сбору данных и руководством по настройке безголового сервера.

Источники

#Безголовый Режим#Обычный Режим#Сравнение Сигналов#Автоматизация#Развёртывание

Эта статья входит в руководство: Развёртывание и выпуск браузера: операционная карта

Переведите BotBrowser из исследований в продакшн

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