- Регистрация
- 10.10.2019
- Сообщения
- 2
- Благодарностей
- 3
- Баллы
- 3
Этот проект появился из-за периодической необходимости отслеживать некрупные изменения на сайтах, вроде переименования элементов или их небольшого изменения. При этом для такой задачи использовать полноценный ИИ-агент кажется избыточным, ведь нужно решить одну конкретную задачу - найти элемент на странице. А далее уже либо получить обновленный селектор и использовать его, либо просто нажать конкретную кнопку на основании скриншота.
Zennoposter AI Fallback Helper — это небольшая библиотека одношаговых AI-действий для ZennoPoster. Каждый метод решает свою задачу самостоятельно: собирает данные из браузера, при необходимости выполняет несколько попыток (например, прокручивая страницу для захвата нужной области), отправляет запрос к API и возвращает результат. Никакой внешней оркестрации не требуется. А так же не требуется каких-то дорогих моделей, при работе с текстом большинстве случаев справляются даже локальные модели. При желании можно самостоятельно дополнять библиотеку своими действиями.
Задачи, которые решаются на данный момент:
- Найти XPath элемента по его текстовому описанию — без написания селектора вручную, ответ можно использовать далее в программе для какого-либо действия уже с помощью самого Zennoposter.
- Кликнуть по элементу, который модель находит визуально по скриншоту исходя из текстового описания - на случай если структура страницы поменялась, но мы знаем какую кнопку все таки нужно нажимать.
Оба метода работают через единый интерфейс провайдера — можно использовать OpenAI, DeepSeek, локальную модель через LM Studio или любой OpenAI-совместимый эндпоинт.
Если технические детали не интересны — листайте сразу к разделу 4 с примерами использования или к разделу 5 для работы через плагин.
Содержание
- Архитектура: одношаговый подход и провайдеры
- Описание методов: FindXPath и ClickByView
- Конфигурация: AiActionConfig
- Примеры использования в C# коде
- Использование как плагин ZennoPoster
1. Архитектура: одношаговый подход и провайдеры
Главное архитектурное решение — один вызов — одна задача. Каждый публичный метод класса
AiActions решает свою задачу самостоятельно — при необходимости выполняя несколько внутренних запросов к API: например, при поиске XPath модель может получить несколько попыток с историей предыдущих ошибок, а при ClickByView с включённой прокруткой — отдельный запрос на каждую позицию страницы. Но всё это происходит внутри одного вызова метода, прозрачно для вызывающего кода.- Собирает данные из браузера (HTML страницы или скриншот)
- При необходимости выполняет внутренние итерации — например, прокрутку страницы для захвата нужной области скриншота
- Формирует запрос к API и получает ответ
- Разбирает ответ и возвращает результат или выбрасывает исключение
Метод либо вернул результат — либо упал с исключением. Промежуточных состояний нет.
Связь с API реализована через интерфейс
IActionApiProvider. Это позволяет менять провайдера не затрагивая логику методов:| Провайдер | Эндпоинт | Особенности |
|---|---|---|
| ResponsesApiProvider | /v1/responses | Используется по умолчанию. Читает ответ из output[].content[type=output_text]. Поддерживает flex service tier |
| CompletionsApiProvider | /v1/chat/completions | Универсальный. Читает ответ из choices[0].message.content. Совместим с DeepSeek, Mistral, LM Studio, Ollama |
2. Описание методов: FindXPath и ClickByView
FindXPath
Находит XPath элемента по его текстовому описанию. Алгоритм работы:
- Забирает HTML активной вкладки и очищает его согласно
XPathHtmlClean - Опционально делает скриншот как дополнительный контекст (при
XPathIncludeScreenshot = true) - Отправляет HTML и описание элемента модели, извлекает XPath из тега
<xpath>...</xpath>в ответе - Проверяет найденный XPath на живой странице через
FindElementByXPath - Если элемент не найден — передаёт модели описание ошибки и повторяет, до
XPathMaxAttemptsраз
C#:
string xpath = aiActions.FindXPath("кнопка отправки формы регистрации");
// Вернёт, например: //button[@type='submit'] или //input[@value='Зарегистрироваться']
ClickByView
Кликает по элементу, определяя его координаты визуально по скриншоту. Алгоритм работы:
- При
SendFullPageScreenshot = true— делает снимок всей страницы целиком и отправляет его модели. Модель видит всю страницу сразу и возвращает координаты элемента - В обычном режиме — прокручивает страницу к накопленной позиции через
window.scrollTo, делает скриншот видимой области, отправляет модели - Модель отвечает одним из трёх вариантов: координаты
<x>N</x><y>N</y>,SCROLL(нужна прокрутка) илиERROR(элемент не найден) - При
SCROLLи включённомClickScrollEnabled— увеличивает позицию прокрутки и повторяет - При получении координат — пересчитывает их в экранные с учётом масштаба и смещения, эмулирует движение мыши и клик
C#:
aiActions.ClickByView("синяя кнопка «Продолжить» в правом нижнем углу");
ZennoPoster работает с абсолютными координатами в пределах вьюпорта профиля. При прокрутке страницы вьюпорт смещается визуально, но система координат ZennoPoster остаётся неизменной. Кроме того, каждый вызов скриншота сбрасывает прокрутку страницы в самое начало — поэтому итеративный подход с прокруткой и повторным скриншотом требует точного восстановления позиции перед кликом, что реализовано через
window.scrollTo с накоплением смещения в переменной.По этой причине рекомендуется отправлять полный скриншот страницы целиком (
SendFullPageScreenshot = true) — тогда модель видит всю страницу сразу и определяет координаты без какой-либо прокрутки.Про выбор модели для работы с изображениями
| Метод | Тип задачи | Требования к модели |
|---|---|---|
FindXPath | Анализ текста (HTML) | Справляются недорогие и локальные модели |
ClickByView | Анализ изображения | Требует модели с поддержкой vision-модели — дешёвые и локальные модели часто ошибаются |
Дешёвые модели и большинство локальных плохо справляются с обработкой изображений: они могут неверно определить координаты, перепутать похожие элементы или вернуть некорректный ответ. Чем сложнее страница визуально — тем выше вероятность ошибки. Для
ClickByView рекомендуется использовать gpt-5.4 так как он показывает себя наиболее точным в распозавании изображений когда нужно находить элементы интерфейса, хотя в целом более слабые модели тоже могут справляться, важно только чтобы контекстного окна хватало для загрузки изображения.Документация OpenAI рекомендует использовать режим
original для задач управления интерфейсом — в этом режиме точность распознавания координат наиболее высокая.В программу намеренно добавлена возможность сжатия изображения (
MaxImageDimension) до нужных размеров (по наибольшей стороне) и отправки только видимой области экрана пользователя — чтобы уменьшить размер передаваемого файла для моделей с ограниченным контекстом. Однако это компромисс: меньший размер изображения снижает точность распознавания. Даже при использовании этих параметров 100% качества не гарантируется.Практический совет: для
ClickByView используйте gpt-5.4 с ImageDetail = "original" и SendFullPageScreenshot = true. Экономия на модели здесь обходится дороже, чем экономия на токенах.Очистка HTML: HtmlCleanLevel
При работе с реальными сайтами HTML-страница может занимать сотни килобайт — большую часть из которых составляют
<script>, <style>, SVG-иконки и инлайновые обработчики событий. Для задачи поиска XPath весь этот мусор бесполезен и только увеличивает расход токенов.Параметр
XPathHtmlClean управляет тем, что именно передаётся модели при вызове FindXPath. Очистка применяется последовательно — каждый следующий уровень включает предыдущий:| Уровень | Что удаляется | Когда использовать |
|---|---|---|
Minimal | <script>, <style>, HTML-комментарии | Страницы где важен SVG, meta или link — например, иконки с aria-label |
Standard | Всё из Minimal + <noscript>, <link>, лишние пробелы и пустые строки | По умолчанию, подходит для большинства задач |
Aggressive | Всё из Standard + <svg>, <meta>, inline-атрибуты style="" и обработчики onclick="" | Тяжёлые страницы, простые формы и листинги, экономия токенов |
Системные промпты
Каждый метод использует свой системный промпт — короткий и жёстко структурированный. Это намеренное решение: чем меньше промпт, тем меньше токенов тратится на каждый вызов, а чёткий формат ответа упрощает его разбор.
FindXPath — модель получает роль эксперта по XPath и жёсткое требование к формату ответа:
Код:
XPath expert. Return XPath for the requested element.
Reply ONLY: <xpath>//expression</xpath>
Prefer @id/@name/@data-* or text. No indexes unless unavoidable. No explanation.
- XPath MUST be on a single line
- No explanations
- Always wrap in <xpath>...</xpath>
- Avoid complex functions unless necessary
@id, [USER=98307]@Name[/USER], @data-*), затем текстовое содержимое, индексы — только если других вариантов нет. Это снижает вероятность получить хрупкий XPath вида //div[3]/span[2]/button[1], который сломается при малейшем изменении вёрстки.ClickByView — модель получает три строго определённых варианта ответа, без каких-либо других возможностей:
Код:
Browser automation. Find the element on the screenshot and reply with EXACTLY ONE of:
1. Coordinates (element visible): <x>N</x><y>N</y>
2. Need to scroll (not visible yet): SCROLL
3. Cannot find (black/broken page): ERROR: reason
Rules:
- Coordinates = pixel center of the element, integers only.
- Use SCROLL if the element is likely below/above the current view.
- Use ERROR only if the page is clearly broken, black, or element cannot exist.
- No extra text, no markdown.
ERROR намеренно ограничен крайними случаями: битая страница, чёрный экран, элемент заведомо не может существовать — чтобы модель не злоупотребляла им при малейших затруднениях.Поскольку модели иногда отвечают не в точном формате, парсер координат поддерживает несколько вариантов записи по убыванию специфичности:
<x>N</x><y>N</y> → x=N, y=N → NxM → N,N. Аналогично для XPath: сначала ищется тег <xpath>...</xpath>, затем любое выражение начинающееся с / или .//.3. Конфигурация: AiActionConfig
C#:
var config = new AiActionConfig
{
// --- Подключение к API ---
ApiKey = "sk-...", // Bearer-токен. Обязательное поле
Model = "gpt-5.4", // Название модели. Обязательное поле
Proxy = "host:port", // Прокси. Пустая строка — без прокси
Provider = new CompletionsApiProvider(
"https://api.deepseek.com/v1/chat/completions"
), // По умолчанию ResponsesApiProvider
TimeoutMs = 120_000, // Таймаут HTTP-запроса в мс
FlexMode = false, // service_tier=flex — дешевле, но медленнее, подробнее можно почитать на сайте самого OpenAI
// --- Скриншоты ---
// Рекомендуется: ImageDetail="original", SendFullPageScreenshot=true
ScreenshotQuality = 70, // Качество JPEG 0–100
ImageDetail = "original", // "low" / "high" / "original"
SendFullPageScreenshot = true, // Снимать всю страницу — рекомендуется для ClickByView
MaxImageDimension = 0, // Макс. сторона изображения. 0 = без лимита
// --- FindXPath ---
XPathMaxAttempts = 3, // количество попыток поиска
XPathIncludeScreenshot = false, // нужно ли отправлять рядом еще и скриншот для лучшего понимания моделью
XPathHtmlMaxLength = 12_000, // ограничние на количество символов, чтобы случайно большое количество токенов не потратилось на какой-то странице
XPathHtmlClean = HtmlCleanLevel.Standard, //описание вариантов есть выше в статье
// --- ClickByView (прокрутка) ---
// Предпочтительнее SendFullPageScreenshot=true без прокрутки.
ClickScrollEnabled = false,
ClickScrollStep = 0,
ClickScrollMaxAttempts = 5,
};
Дополнительно параметр
XPathHtmlMaxLength обрезает HTML до заданного числа символов уже после очистки. Значение -1 — без ограничения.4. Примеры использования в C# коде
Здесь я приведу только небольшие примеры того как это работает, сам код проекта находится в прикрепленныш шаблонах, в общем коде и вы можете его самостоятельно посмотреть, он сопровождем комментариями, не стал добавлять сюда, чтобы не увеличивать сильно размеры статьи.
Важно: Так как в текущем виде весь код находится в отдельном namespace, для того чтобы можно было его вызвать в вашем проекте после копирования этого кода, нужно так же добавить
using ZennoposterAiAgentCore; в "Директивы Using"
C#:
var config = new AiActionConfig
{
ApiKey = project.Variables["api_key"].Value,
Model = "gpt-5.4",
};
var ai = new AiActions(project, instance, config);
// Найти XPath кнопки по описанию и кликнуть через ZennoPoster
string xpath = ai.FindXPath("кнопка подтверждения заказа");
instance.ActiveTab.FindDomElement(xpath).Click("left", "click");
// Или кликнуть напрямую по визуальному расположению
ai.ClickByView("кнопка подтверждения заказа");
C#:
var config = new AiActionConfig
{
ApiKey = project.Variables["api_key"].Value,
Model = "gpt-5.4",
ImageDetail = "original",
SendFullPageScreenshot = true,
ScreenshotQuality = 80,
};
var ai = new AiActions(project, instance, config);
ai.ClickByView("кнопка «Оформить заказ» в блоке итоговой суммы");
C#:
var config = new AiActionConfig
{
ApiKey = "",
Model = "qwen/qwen3.5-9b",
Provider = new CompletionsApiProvider(
"http://localhost:1234/v1/chat/completions"),
XPathHtmlClean = HtmlCleanLevel.Aggressive,
XPathHtmlMaxLength = 5000,
};
var ai = new AiActions(project, instance, config);
string xpath = ai.FindXPath("поле ввода email в форме регистрации");
C#:
var config = new AiActionConfig
{
ApiKey = project.Variables["deepseek_key"].Value,
Model = "deepseek-chat",
Provider = new CompletionsApiProvider(
"https://api.deepseek.com/v1/chat/completions"),
};
ResponsesApiProvider подставляется по умолчанию — явно указывать его не нужно.
C#:
var config = new AiActionConfig
{
ApiKey = project.Variables["api_key"].Value,
Model = "gpt-5.4",
ImageDetail = "original",
SendFullPageScreenshot = true,
MaxImageDimension = 1280, // Уменьшит файл, но снизит точность
};
var ai = new AiActions(project, instance, config);
ai.ClickByView("иконка корзины в шапке сайта");
5. Использование как плагин ZennoPoster
Для тех, кто предпочитает работать без написания C# кода — доступен плагин с графическим интерфейсом. Настройки задаются в кубике, результат передаётся в переменную проекта.
Как это работает
Плагин принимает описание элемента, выполняет один из двух режимов и записывает результат в переменную
aiActionsResult:- Режим FindXPath — возвращает XPath найденного элемента в виде строки, например
//button[@id='submit'] - Режим ClickByView — выполняет клик и возвращает строку
ok
При неудаче плагин выбрасывает исключение — выполнение шаблона прерывается стандартным образом ZennoPoster.
Описание настроек — вкладка «Главные»
| Настройка | Описание |
|---|---|
| Ключ API | Bearer-токен для авторизации. Для локальных моделей можно оставить пустым |
| Имя модели | Идентификатор модели, например gpt-5.4 или deepseek-chat |
| Тип провайдера API | Responses — для OpenAI. Completions — для DeepSeek, LM Studio, Ollama и прочих совместимых |
| Адрес для вызова API | Полный URL эндпоинта. Пустое поле — используется стандартный адрес OpenAI для выбранного типа провайдера |
| Прокси | В формате host:port или login:pass@host:port. Пустое — без прокси |
| Режим работы | FindXPath или ClickByView |
| Описание элемента | Текстовое описание того, что нужно найти или на что кликнуть |
| Таймаут (мс) | Максимальное время ожидания ответа от API. По умолчанию 120 000 мс |
| Flex mode | Пониженный приоритет запроса — дешевле, но медленнее. Только для ResponsesApiProvider |
Описание настроек — вкладка «Дополнительные»
| Настройка | Описание |
|---|---|
| Макс попыток XPath | Сколько раз модель может предложить новый вариант XPath при неудаче. По умолчанию 3 |
| Скриншот при поиске XPath | Прикладывать скриншот к запросу FindXPath как дополнительный контекст |
| Макс символов HTML | Лимит символов HTML, передаваемых модели. -1 = без ограничения |
| Очистка HTML | Minimal / Standard / Aggressive — степень удаления мусора из HTML перед отправкой |
| Полный скриншот страницы | Снимать всю страницу целиком, а не только вьюпорт. Рекомендуется для ClickByView |
| Детализация изображения | original рекомендован OpenAI для управления интерфейсом — наибольшая точность координат |
| Макс сторона изображения | Ограничить размер скриншота в пикселях. 0 = без лимита. Снижает размер файла, но и точность |
| Качество скриншота | 1–100. По умолчанию 70 |
| Прокрутка при ClickByView | Прокручивать страницу в поисках элемента. Не рекомендуется при включённом полном скриншоте |
| Макс попыток прокрутки | Сколько раз прокручивать страницу до отказа. По умолчанию 5 |
| Шаг прокрутки в пикселях | 0 = прокручивать на высоту вьюпорта за раз |
Ограничения плагина
- Результат только один: XPath-строка или
ok— без токенов, стоимости и отладочного лога - Для получения дополнительной информации о выполнении используйте C# код напрямую
Что умеет библиотека:
- Находить XPath любого элемента по его текстовому описанию
- Кликать по элементу, который модель находит визуально на скриншоте
- Работать с OpenAI, DeepSeek, LM Studio, Ollama и любым OpenAI-совместимым провайдером
- Настраивать объём передаваемого HTML — от полного до агрессивно сжатого
- Отправлять полный скриншот страницы для точного определения координат без прокрутки
- Использоваться как плагин без написания кода
Чего библиотека не делает и о чём стоит знать:
- Не гарантирует результат на любой странице — нестандартная вёрстка и визуально сложные интерфейсы повышают вероятность ошибки, особенно при использовании слабых или локальных моделей
- Дешёвые и локальные модели плохо справляются с анализом изображений — для
ClickByViewрекомендуетсяgpt-5.4 - Координаты ZennoPoster всегда абсолютные относительно видимой области — прокрутка смещает видимую область, но не систему координат; каждый скриншот сбрасывает страницу вверх, поэтому при в таком режиме приходится листатать страницу несколько раз, что отражается на времени выполнения.
- Не работает бесплатно — каждый вызов метода это запрос к API (кроме локальных моделей), здесь экономику работы стоит подсчитывать самостоятельно, в каком проекте и когда есть смысл использовать такой код.
В прикреплённом файле находится полный исходный код, а также плагин для прямого использования в шаблонах и сам исходный код плагина для собственного редактирования. Внешних зависимостей нет — только стандартные возможности ZennoPoster и C#.
Подробнее про установку плагинов можно прочитать в в официальной документации ZennoLab: https://zennolab.atlassian.net/wiki/spaces/RU/pages/475365697
На видео я продемонстрировал несколько примеров использования как напрямую из кода, так и с помощью плагина на lessons.zennolab.com:
Проект открыт для изучения и доработки. Используйте на свой страх и риск — автор не берёт на себя ответственность за сбои в работе или расходы на API. В коде могут иметься ошибки и баги. Будьте внимательны при его использовании.
Вложения
-
63,4 КБ Просмотры: 3
-
35,2 КБ Просмотры: 2
-
87,2 КБ Просмотры: 2
Последнее редактирование модератором:


