Перейти к содержимому
PD
EN RU
Browser Automation Studio 7 мин чтения

Попап всё равно вылезет: слой обработки помех для BAS-скриптов

Cookie-баннеры, модалки с подпиской, слетевшая сессия и внезапные A/B-тесты ломают BAS-скрипты чаще, чем кривые селекторы. Рассказываю, как я строю слой обработки помех в каждом проекте на Browser Automation Studio.

PD

Pavel Duglas

AI Automation & MVP Architect

Почти каждый BAS-скрипт, который мне приносили на разбор, ломался по одному сценарию. Две недели всё работало, а потом в одно утро половина потоков начала падать на клике, который до этого прошёл десять тысяч раз. Селектор на месте, страница на месте. Просто cookie-баннер поменял разметку, или модалка «подпишитесь на рассылку» стала вылезать на третьем просмотре, или сайт начал показывать «оцените нас» посетителям из одной конкретной страны. Нужный элемент никуда не делся, его просто накрыло тем, чего никто не ждал.

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

Проблема не в селекторах

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

Скрипт живёт в линейном мире: открыл страницу, нажал «Войти», ввёл email, отправил. Реальные сайты так не работают. Это основной сценарий плюс облако всего, что может выскочить в любой момент: окна согласия, промо-модалки, чат-виджеты, которые выезжают поверх кнопок, экран «сессия истекла», A/B-тесты, двигающие кнопку, капча, страница техработ. Если скрипт знает только основной сценарий, каждая такая штука превращается в падение.

Решение в том, чтобы разделить две вещи:

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

Три типа помех

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

1. Закрываемые оверлеи

Cookie-баннеры, окна подписки, предложения поставить приложение, чат-виджеты, плашки «мы используем cookies» внизу экрана. Они перекрывают клики, но закрыть их безопасно. Реакция: закрыть и ехать дальше.

2. Смена состояния

Сессия истекла, принудительный разлогин, экран «подтвердите, что это вы», капча, проверка возраста, выбор региона. Крестик тут не поможет, скрипту нужно сделать что-то осмысленное: перелогиниться или пройти проверку. Реакция: запустить процедуру восстановления и вернуться к известной контрольной точке.

3. Жёсткая остановка

Аккаунт забанен, страница техработ, 403 от прокси, товар удалён. Реакция: остановить эту задачу, записать причину и идти к следующей. Повторять попытки на бане - лучший способ сжечь весь пул прокси.

Если эти корзины перепутать, начинается веселье. Скрипт, который считает капчу обычным попапом, бесконечно тыкает по странице. Скрипт, который считает бан таймаутом, ретраит его пятьдесят раз.

Слой помех: одна функция на контрольных точках

В BAS я оформляю это как одну функцию, обычно HandleInterruptions. Каждый важный шаг сценария вызывает её перед действием. Функция смотрит на текущую страницу, определяет, к какой корзине относится ситуация, и возвращает результат, на который может отреагировать сценарий: clear, recovered или stop с причиной.

Реестр вместо кучи условий

Известные помехи внутри функции хранятся как данные, а не как размазанная по скрипту логика. У каждой записи есть:

  • name: cookie_banner_v2, newsletter_modal, session_expired
  • detector: селектор или проверка текста, по которой помеха опознаётся
  • type: оверлей, смена состояния или жёсткая остановка
  • action: селектор для клика или имя функции восстановления
  • max hits: сколько раз за задачу запись может сработать

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

Порядок проверки важен. Сначала жёсткие остановки, потом смена состояния, потом оверлеи. Если под cookie-баннером висит сообщение о бане, вам нужно узнать про бан, а не радостно закрыть баннер и продолжить работу в мёртвом аккаунте.

Где вызывать

Не перед каждым блоком, иначе скрипт будет ползти. Я вызываю обработчик в трёх местах:

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

Третий пункт самый ценный. Оборачивайте важные шаги так, чтобы ошибка не убивала поток сразу. Схема простая: пробуем шаг, если упал, запускаем HandleInterruptions, если вернулось clear или recovered, повторяем шаг один раз, иначе пробрасываем ошибку выше.

Ограничивайте всё

Слой помех без лимитов - это бесконечный цикл, который просто ждёт своего часа. Модалка, которая появляется снова после каждого закрытия. Логин, который редиректит обратно на логин. Сервис капчи, который раз за разом не справляется. Я ставлю три лимита:

  • Срабатывания одной записи за задачу, обычно 2 или 3.
  • Общее число вызовов обработчика за задачу, около 10.
  • Число восстановлений за задачу, обычно 1 или 2 перелогина.

Когда лимит исчерпан, результат становится stop с причиной вроде loop:newsletter_modal. При разборе логов такая причина на вес золота.

Не закрывать, а предотвращать

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

  • Выставляйте согласие заранее. Большинство систем согласия хранят решение в cookie или localStorage. Примите баннер один раз руками, посмотрите, что записалось, и проставьте те же значения в профиле или через JavaScript до первой рабочей навигации. Многие баннеры после этого просто не рисуются.
  • Блокируйте сторонние виджеты. Чаты, опросники и часть систем согласия грузятся с известных доменов. Отрубите эти URL через блокировку запросов в BAS. Бонусом страницы грузятся быстрее и меньше жрут трафик прокси.
  • Переиспользуйте профили. Вернувшийся профиль с куками видит меньше модалок для новых посетителей, чем свежий профиль каждый раз.
  • Держите окружение согласованным. Если прокси немецкий, язык браузера русский, а часовой пояс вьетнамский, ждите выбор региона, дополнительные проверки и странную вёрстку. Согласованность убирает целый класс помех.
  • Посмотрите в сторону HTTP-клиента. Если нужные данные приходят из API, которое дёргает страница, режим HTTP-клиента в BAS обходит весь визуальный слой. Ни баннеров, ни модалок. Получается не всегда, но проверять стоит в первую очередь.

Даже после этого я оставляю записи про оверлеи в реестре: системы согласия обновляются, формат куки меняется. Предотвращение снижает частоту, обработчик закрывает дыры.

Проверяйте «я на той странице?», а не только «элемент есть?»

Есть тихий тип сбоя: скрипт находит элемент с правильным селектором, но на неправильной странице. Форма логина на экране истёкшей сессии, кнопка «Отправить» внутри модалки, цена рекомендованного товара вместо основного. Шаг формально успешен, а данные - мусор.

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

Так «скрипт сделал что-то странное» превращается в «ждали карточку товара, получили выбор региона», а это уже можно чинить.

Неизвестные помехи должны шуметь

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

  • id задачи и номер потока
  • URL и заголовок страницы
  • шаг, на котором упало
  • скриншот
  • HTML страницы в отдельный файл
  • использованные прокси и профиль

Раз в день я смотрю неизвестные блокеры, сгруппированные по URL и заголовку. Обычно два-три паттерна покрывают почти всё. Каждый паттерн становится новой записью в реестре. Через пару недель доля неизвестных падает почти до нуля, а новые всплески сообщают мне об изменениях на сайте раньше, чем об этом напишет клиент.

И ещё: считайте каждое срабатывание обработчика, даже успешное. Если cookie_banner_v2 вдруг срабатывает в 100% задач вместо 5%, сломалось предотвращение. Если подскочил session_expired, сайт мог сократить время жизни сессии или начать помечать ваши профили. Эти счётчики - система раннего предупреждения, которая достаётся почти бесплатно.

Чеклист для нового BAS-проекта

  • Сначала пишем HandleInterruptions как функцию, потом основной сценарий.
  • Известные помехи храним как данные: детектор, тип, действие, лимит.
  • Проверяем жёсткие остановки, потом смену состояния, потом оверлеи.
  • Вызываем обработчик после навигации, перед критичными действиями и при ошибке.
  • После обработчика повторяем упавший шаг один раз, никаких открытых циклов.
  • Ставим лимиты на запись, на задачу и на восстановления.
  • Предотвращаем согласия и виджеты через куки, storage и блокировку запросов.
  • Проверяем идентичность страницы перед парсингом и отправкой.
  • Логируем неизвестные блокеры со скриншотом и HTML, разбираем каждый день.
  • Считаем срабатывания по каждой записи и реагируем на резкие изменения.

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

Вопросы и ответы

Не замедлит ли обработчик помех работу скрипта?

Если вызывать его перед каждым блоком, замедлит. Поэтому я вызываю его только после навигации, перед критичными действиями и при ошибке. Проверка реестра из десятка селекторов занимает доли секунды, а ретрай после ошибки срабатывает только тогда, когда что-то реально пошло не так. В итоге скрипт работает почти с той же скоростью, но падает в разы реже.

Как обрабатывать капчу внутри такого слоя?

Капча относится ко второй корзине, к смене состояния. В реестре у неё в action указано имя функции восстановления, которая отправляет капчу в сервис распознавания и проверяет результат. Обязательно ставьте лимит: если капча не прошла один-два раза, задача получает stop с причиной, а не крутится бесконечно. Частый рост капчи в счётчиках - сигнал проверить качество прокси и согласованность профилей.

Что делать, если сайт постоянно меняет разметку попапов?

Делайте детекторы устойчивее: опирайтесь на текст, роли, атрибуты вроде aria-label или data-атрибуты, а не на сгенерированные классы. Параллельно максимально предотвращайте появление попапов через куки согласия и блокировку сторонних скриптов. А логирование неизвестных блокеров со скриншотом и HTML позволяет добавить новую запись в реестр за пару минут, не трогая основной сценарий.

Похожие статьи

Сделаю под ключ

Не хотите собирать сами? Соберу бота на BAS под вашу задачу

Многопоточность, прокси, антидетект-профили и запуск по расписанию. Весь проект и доступы остаются у вас.

от 15 000 ₽ · 3-7 дней

Похожий кейсiHerb + PochtaGlobal - автоматизация бизнес-процессовБот для реселлера товаров из США: сам собирает заказы с iHerb, оформляет покупки и посылки на PochtaGlobal, следит за трек-номерами и сообщает о каждом шаге в Telegram и в учётную систему.

«Павел крутой специалист выполнил парсер за несколько часов. Буду заказывать у Павла еще и еще! Спасибо ему огромное за его профессионализм и оперативность!»

volodymyrlemchenko · Kwork
  • #Browser Automation Studio
  • #BAS
  • #Web Automation
  • #Reliability
  • #Scraping

Есть идея? Давайте превратим её в работающий продукт.

Получите понятную архитектуру, рабочий MVP и систему, которую можно тестировать, продавать и масштабировать.

Или оставьте заявку здесь

Заявка приходит мне в Telegram. Обычно отвечаю в течение нескольких часов.