CNN TürkGalatasaray’da Leroy Sane için ayrılık senaryosuPunchWhite House reaffirms US policy recognising only two gendersInquirerHeatwave fuels 54% fire surge in Northern MindanaoThe Jerusalem PostBrazilian lawyer convicted of racism after calling for Jews to be removed from leadershipBollywood HungamaPriyanka Chopra Jonas announces Ventilator 2, reunites with director Rajesh Mapuskar; film set for 2027 release한겨레삼성, 12년 만의 한국시리즈 우승 1승 남았다ZDF heuteEntdecken Sie das ZDF-NachrichtenstudioIl Sole 24 OreCaro gasolio e tir, in Sicilia 15 milioni fermi: ma le domande scadono a fine meseХабр[Перевод] Восстановление готических соборов при помощи станков с ЧПУVanguardParaguay Senate impeaches President Peña, VP Alliana takes overSportstarभारत बनाम न्यूजीलैंड लाइव स्कोर, दूसरा वनडे: भारत 86/5, जीत के लिए 49 रन चाहिए; श्रेयस 30 रन बनाकर आउट हुएThe Sydney Morning HeraldSingapore Airlines First Class suites
The Daily Newsstand · Free, Always
Saturday, November 7, 2026

Как мы с локальной LLM легально победили жесткий антифрод и создали визуально-текстового DOM-агента в обход блокировок

Translate

DISCLAIMER: Автор статьи категорически осуждает злонамеренное использование методов и способов массового и деструктивного автоматизированного сбора данных с любых сайтов объявлений и обсуждение подобных методов. Цель статьи в другом - рассказать о том как можно искать нужное, не нарушая при этом правил.

Эта история о том, как обычная задача по поиску редкого оборудования на вторичном рынке превратилась в полноценное инженерное исследование. В итоге мне удалось научить локальную языковую модель класса 7B/8B (Qwen) обходить агрессивные системы защиты, обфусцированный фронтенд и сетевые ограничения изолированной песочницы. Никакого платного API поисковиков, никаких прокси. Только Python, Playwright и пиксельно-логический подход. Статья написана по горячим следам нашего с ИИ “технологического прорыва”.

Предыстория и боль: Почему requests к крупным сайтам - это гарантированный бан.

Задача казалась тривиальной: попросить локальную модель в среде Strata найти объявления о продаже флагманской мобильной рабочей станции в максимальной комплектации с редкой профессиональной видеокартой на популярном сайте объявлений. Но современные крупные площадки объявлений обладают просто свирепой системой защиты от ботов. Попытка сделать прямой requests.get() или использовать стандартный BeautifulSoup моментально упирается в банальные “HTTP 403 Forbidden” или “HTTP 429 Too Many Requests”. Работу модели мгновенно отсекал WAF (веб-инструмент защиты) на сетевом уровне.

Тогда я попытался использовать классическую «прослойку» - научить модель искать объявления через поисковые системы (Google, Яндекс, DuckDuckGo) с оператором site:domain.ru. Но и тут меня ждало фиаско! Один поисковик выдал типовую заглушку «Вы не робот», которую текстовый скрипт не мог пройти. Текстовое HTML-зеркало второго поисковика намертво зависало по таймауту из-за сетевого allow-list’а внутри изолированного окружения Strata. Третий поисковик отдавал живой HTML, который при парсинге оказывался пустой JavaScript-заглушкой перенаправления.

Модель раз за разом выдавала ноль результатов, путалась в регулярных выражениях и ломала URL-адреса. Стало понятно: стандартные методы веб-скрейпинга если и не мертвы, то требуют крайне нетривиальных методов на грани фола. Нужно было менять саму архитектуру взаимодействия.

Найденный метод: Визуально-текстовый DOM-агент прямого действия (Visual Web Agent).

Вместо того чтобы пытаться обмануть сеть на уровне сырых пакетов, я решил попросить модель сымитировать человека на пиксельном и логическом уровнях. Метод базируется на “двух китах”: эмуляции реального браузера системы и парсинге DOM-дерева по «человеческим» маркерам вместо завязки на CSS-классы.

Шаг 1. Браузерный «плащ-невидимка» - эмуляция системного Edge.

Антифрод-системы легко вычисляют headless-браузеры Playwright или Selenium по специфическим флагам (например, navigator.webdriver = true). Поэтому я попросил модель перехватить управление уже установленным в операционной системе браузером Microsoft Edge, и модель мигом собрала скрипт на Python.

Скрипт запускается в видимом режиме (headless=False), используя системный бинарник браузера через параметр channel=“msedge”. Дополнительно в аргументы передаются флаги --start-maximized и --focus, а в коде вызывается метод page.bring_to_front(). Это принудительно выталкивает окно браузера из трея прямо на экран поверх всех окон. Для систем защиты это выглядит как абсолютно легитимный запуск страницы пользователем. Пауза в 8 секунд гарантирует, что все скрипты защиты успеют отработать, а страница - полностью прогрузиться.

Шаг 2. Победа над обфускацией: Парсинг по текстовым маркерам.

Фронтенд крупных платформ перегружен хэшированными динамическими классами (например, .styles-module-root-XyZ12), которые генерируются сервером случайным образом и меняются при каждом обновлении сайта. Но и тут модель оказалась на высоте и принципиально стала игнорировать CSS-селекторы. Агент сканирует DOM-дерево в один проход, цепляясь за смысловые текстовые маркеры:

  1. Находит текстовый узел, содержащий знак валюты (или другой маркер цены) - это становится точкой фиксации.

  2. Поднимается к родительскому контейнеру и забирает соседний крупный текст - это заголовок.

  3. Извлекает из этого же блока ссылку, валидируя её регулярным выражением на наличие паттерна _\d{5,} (уникальный цифровой ID объявления в хвосте URL карточки).

Шаг 3. Сборка разнесенных данных по Item ID (iid).

Архитектура современных маркетплейсов часто разносит данные в целях оптимизации: имя продавца и его город могут лежать за пределами компактного контейнера карточки. Локальная модель сама нашла изящное решение: она обнаружила, что ссылки на профили магазинов в коде страницы имеют жесткий параметр привязки к карточке (например, ?iid=, где - это уникальный ID объявления). Скрипт, тут же совершенно самостоятельно оптимизированный моделью, стал снимать сквозной текстовый дамп страницы, находить совпадения по iid и склеивать пары «товар + цена + город + ссылка на продавца» со 100% точностью, полностью исключая смещение строк при выводе отчета.

В итоге я практически занял позицию наблюдателя, который просто сидел и смотрел на то, как «художник творит», получив в конце работы модели спарсенные объявления и ссылки!

Универсальный промпт-контейнер для запуска ИИ-агента.

В результате «родился» простой и универсальный промпт-контейнер для запуска ИИ-агента под описанную задачу. Чтобы ваша локальная (или облачная) модель сразу поняла этот метод и применила его к любому другому сложному сайту, не сваливаясь в requests и не пытаясь скачать встроенный Chromium (что часто ломает окружение), вы можете использовать следующий проверенный промпт-контейнер:

Запусти режим «Визуально-текстового DOM-агента прямого действия». Твоя задача - найти [что ищем] на сайте [имя сайта здесь].

Действуй строго по алгоритму:

  1. Не используй requests и не пытайся скачивать встроенные браузеры библиотеки Playwright.

  2. Запускай браузер в видимом режиме (headless=False), жестко прописав использование уже установленного Edge через параметр: channel=“msedge” (это отменит скачивание Chromium из сети).

  3. Чтобы окно не оставалось свернутым в трее, обязательно передай в args запуска браузера флаги: “–start-maximized” and “–focus”, а после создания страницы вызови метод page.bring_to_front(), чтобы принудительно поднять окно на передний план экрана поверх всех окон.

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

  5. Выдержи паузу в 8 секунд после загрузки для обхода систем защиты и Cloudflare.

  6. Сделай скриншот для визуального контроля и OCR-анализа.

  7. Игнорируй хэшированные CSS-классы. Собирай данные (название, цена, ссылка) через проход по структуре DOM, зацепляясь за текстовые маркеры (знаки валют, паттерны ID карточек).

  8. Если данные разнесены в DOM, сними сквозной текстовый дамп страницы и сопоставь блоки по индексам (например, через Item ID объявления).

Напиши код скрипта, выполни его прямо сейчас через инструмент запуска и выведи готовый отчет с объявлениями в чат.

Результаты: Что в итоге принес мой «автономный робот»?

Несмотря на то, что в процессе плотной интерактивной отладки скрипта целевой сайт в итоге выдал временное ограничение “429” на шестом заходе, модель проявила высокий уровень автономности. Она не растерялась, заблокировала новые сетевые запросы (пока “отвиснет” бан по IP) и собрала финальный структурированный отчет из уже сохраненных в памяти локальных буферов данных.

Самое интересное: ИИ-агент проявил элементы критического мышления. В одном из объявлений в заголовке было указано топовое название видеокарты, но модель просканировала DOM-текст описания и обнаружила строчку продавца: «Видеокарта: младшая серия на 16 гб». Модель сама вынесла в отчет предупреждение: «Внимание, противоречие в спецификации заголовка и описания, уточнять у продавца». Тем самым модель дала мне понять, что объявление мне не подходит даже при формальном “попадании” в запрос.

Заключение.

Ценность этого эксперимента - не конкретные файлы скриптов или json-логи, оставшиеся на диске, и не «изобретение велосипеда». Да и любой профессионал нашел бы куда как более серьезное решение. Главное тут - это доказательство концепции (PoC). Локальная модель класса 7B/8B уже легко способна выступать полноценным автономным ИИ-оператором вашего компьютера!

Объединяя «глаза» (визуальный контроль через скриншоты) и «руки» (управление DOM-деревом через системный браузер), локальная LLM становится практически неуязвимой для стандартных сетевых блокировок. Она может “видеть” интернет точно так же, как его видит живой пользователь.

И это всё больше приближает LLM к той самой, сакраментальной концепции, из слов одной легендарной электронной композиции: «Я твой слуга, я твой рАботник»*…

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.