С инженерной точки зрения поиск работы — это процесс с низкой энтропией. Есть входящий поток данных (JSON с вакансиями) и есть необходимость отправить ответный сигнал (POST-запрос с откликом). Задача кажется тривиальной для автоматизации: написал парсер, настроил cron, пошел пить кофе.
Однако, если вы попробуете автоматизировать отклики на крупных job-board платформах (особенно на hh.ru) в 2026 году, вы столкнетесь с серьезным противодействием. WAF (Web Application Firewall), анализ TLS-отпечатков, поведенческая биометрия и теневые баны — это реальность, которая убивает скрипты на requests за пару часов.
В этой статье разберем архитектуру решения, которое позволяет автоматизировать процесс отклика, используя подходы RPA (Robotic Process Automation), мимикрию под поведение пользователя (Human Mimicry) и LLM для обхода смысловых фильтров.
(Дисклеймер: Статья носит исследовательский характер. Мы не призываем нарушать правила площадок, а разбираем технические методы эмуляции браузера).
Проблема 1: Почему requests больше не работает
Эпоха, когда можно было притвориться браузером, просто подставив User-Agent в заголовки, прошла лет 5 назад.
Современные системы защиты (Akamai, Cloudflare, Qrator и самописные решения площадок) анализируют TLS Fingerprint (JA3/JA3S). Стандартный клиент Python (будь то requests, aiohttp или httpx) имеет характерный порядок шифров при SSL-рукопожатии, который кардинально отличается от реального Chrome или Safari.
Симптомы:
Вы получаете
403 Forbiddenна первый же запрос.Вам отдают страницу с бесконечной капчей.
Можно использовать библиотеки с подменой TLS (например, curl_cffi), но это решает проблему только для парсинга (GET-запросы). Для совершения отклика (нажатие кнопок, ввод текста, работа с динамическим JS) необходим полноценный браузер.
Проблема 2: Headless Browser и его детекты
Мы переходим к Selenium или Playwright. Запускаем браузер в режиме headless=True (без графического интерфейса), чтобы экономить ресурсы сервера.
И тут нас ловит защита на клиенте (в JS).
Существует сотни признаков, выдающих бота:
navigator.webdriver = true— классика.WebGL Fingerprint: У серверных видеокарт (которые рендерят страницу в headless) вендоры — это
Google SwiftShaderилиVMware, а неNVIDIAилиIntel Iris.Отсутствие плагинов: У живого человека всегда есть какой-то мусор в объекте
navigator.plugins.Размер окна: Дефолтный
800x600сразу выдает бота.
Решение: Патчинг на уровне браузера
Использование stealth-plugin для Puppeteer/Playwright помогает, но ненадолго.
Для стабильной работы мы используем кастомные сборки Chromium, где на уровне исходного кода вырезаны флаги автоматизации. Плюс — жесткая привязка профиля:
Каждому воркеру выдается уникальный «цифровой слепок» (Fingerprint).
Используются резидентские прокси (Datacenter IP моментально флагаются).
Проблема 3: Поведенческая биометрия (Behavioral Analysis)
Допустим, мы обошли технические проверки. Браузер выглядит как настоящий. Мы находим кнопку «Откликнуться» и кликаем.
Бан.
Почему? Потому что скрипт наводит курсор мгновенно. Или по идеальной прямой линии.
Современные скрипты антифрода пишут трек движения мыши. Человеческая рука имеет тремор, инерцию, разгон и торможение.
Реализация Human Mimicry (Кривые Безье)
Чтобы обойти это, мы написали модуль движения курсора, основанный на кубических кривых Безье.
Псевдокод логики движения:
Python
import numpy as np
def generate_human_path(start_x, start_y, end_x, end_y):
# Добавляем случайные контрольные точки для отклонения от прямой
ctrl_1_x = start_x + np.random.randint(-50, 50)
ctrl_1_y = start_y + np.random.randint(-50, 50)
# Генерируем точки кривой Безье
t = np.linspace(0, 1, num=50) # 50 шагов анимации
path_x = (1-t)**3 * start_x + 3*(1-t)**2 * t * ctrl_1_x ...
# Важно: добавить "шум" (микро-дрожание)
noise = np.random.normal(0, 1.5, size=len(path_x))
return path_x + noise, path_y + noise
Кроме того, бот никогда не жмет кнопку сразу. Он:
Скроллит страницу вниз (эмуляция чтения).
Делает паузу (Random Sleep от 3 до 12 секунд).
Выделяет текст (иногда).
Только потом кликает.
Архитектура системы
Чтобы масштабировать это решение (один браузер потребляет до 1 ГБ RAM), мы пришли к следующей архитектуре:
Core (Python/FastAPI): API-шлюз и база данных (PostgreSQL).
Orchestrator: Очередь задач (Redis). Контролирует лимиты. Важно: мы не разрешаем отправлять более 20 откликов в сутки с одного аккаунта, чтобы не триггерить поведенческие аномалии на бэкенде платформы.
Browser Nodes: Docker-контейнеры с Playwright. Поднимаются on-demand, отрабатывают сессию и умирают, очищая память.
LLM Module: Self-hosted Llama (или API OpenAI) для генерации текста.
Зачем здесь LLM?
Парсинг верстки: CSS-селекторы меняются. Мы скармливаем LLM кусок DOM-дерева и просим вернуть JSON с описанием вакансии. Это устойчивее к редизайну сайта.
Генерация Cover Letter: Шаблонные письма («Прошу рассмотреть...») имеют низкую конверсию. Модель читает вакансию и пишет ответ, подсвечивая релевантный опыт из резюме.
Автоматизация карьерной рутины — это классическая задача "Red Team vs Blue Team". На каждое действие (улучшение скрипта) платформа отвечает противодействием (новые метрики детекта).
В 2026 году написать простой скрипт для поиска работы уже невозможно. Порог входа вырос до уровня разработки полноценной RPA-системы с элементами AI. Стоит ли оно того? Учитывая, что это экономит десятки часов на механический скроллинг ленты — определенно да.
P.S. Где посмотреть тесты?
Мы проводим открытое тестирование системы. Публикуем логи обхода защит, сравниваем конверсию «ручного» поиска против RPA и делимся статистикой по офферам в разных грейдах.
Кому интересна техническая сторона вопроса или хочется протестировать агента на своем профиле — welcome в наш канал: [Ссылка на ТГ-канал]
Комментарии (14)

nikulin_krd
07.01.2026 06:01Зачем здесь LLM?
Внятного ответа на этот вопрос мы так и не получили.
Вместо того, чтобы пользоваться стандартным функционалом playwright - локаторы, вы на кой-то черт впихнули туда LLM….
Про остальное я вообще молчу.

akakoychenko
07.01.2026 06:01Ага. Странный ход. Логично, что сайты, написанные белками-истеричками, намеренно говнят DOM (например, хз, как сейчас, но 5 лет назад инстаграм выводил текст кусочками по 1й-2м буквам в элементе), есть кейсы, когда интернет магазины специально цену от балды пишут в элементе, перекрытом другим, и так далее. И логично то, что единственный надёжный способ тут это OCR. В теории, если верстку пересобирают, условно, раз в сутки, то, возможно, самым производительным вариантом будет при помощи LLM писать высокопроизводительный парсер, давая DOM + результат OCR, чтобы LLM автоматически писал код, либо конфигурацию парсера, после каждого изменения на стороне НН.
Но вот каждый раз дергать LLM на каждом цикле выглядит и ненадежным (ибо, почему нейронка должна адекватно спарсить намеренно запутанный DOM?), и более затратным, чем OCR, которые сегодня реально быстрые и эффективные

Ilya_JOATMON
07.01.2026 06:01Кстати насчет OCR. Можете что посоветовать, когда сайты с текстами тоже "шифруются" и напрямую текст не вытащить ни копипастой ни залезанием в http. Пробовал сделать скриндамп плагином хрома, это работает, но вот найти OCR которая дальше эту картинку распознает, с этим возникла проблема. Файнридеры отказались - кроме 9й, но там проблема с большими дампами - оно память выделить не может. gImageReader - тоже страдает от размеров дампа и распознает "не очень".

akakoychenko
07.01.2026 06:01Из классики, гляньте на EasyOCR, paddlepaddle
Из интересного нового, microsoft omniparser. Хотя, слишком тяжеловесное решение
Ну, или, если задача не требует эффективности, любая state-of-the-art LLM неплохо OCRит (но, тут, понятно, стоимость будет неадекватной)

nikulin_krd
07.01.2026 06:01Если изучить как работают локаторы в playwright, то не нужны будут ни LLM, ни OCR))

AlexeyK77
07.01.2026 06:01Вместо тега "информационная безопасность" более подходящим будет тег "фрод".

tarantula58910
07.01.2026 06:01вы сотрудник, акционер или бенефициар ХХ ?
если нет, нет и нет, то зачем ущемляетесь на пустом месте ?upd: фрод это другое. например разместить вакансию "тайный покупатель", а вербовать дропов,
которые под предлогом проверки качества обслуживания будут получать пластик на свои документы и
отдавать его кому скажут. или - заполнить анкету от "работодателя" на стороннем ресурсе и отослать ее якобы через телеграм, но этот "телеграм" ваши креды украдет а аккаунт угонит.
AlexeyK77
07.01.2026 06:01не имею отношения к вышеупомянутым организациям, но замечу, что название статьи говорит само за себя "RPA против Anti-Fraud".

exelens
07.01.2026 06:01А не проще ли сделать расширение для браузера, и пусть оно во вкладке отрабатывает?
ingeniare
Все круто конечно, но у HH есть API. Я ещё год назад написал автоотзовик на HH, когда искал работу (так и не нашёл кстати) - он сам искал релевантную вакансию по моему резюме и отзывался. Ну а я потом смотрел отказы, от ещё более тупых ботов с той стороны. HH площадка ботов.
somech
API для соискателя прикрыли