AI-агент для автоматизации браузера (Web Agent)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-агент для автоматизации браузера (Web Agent)
Средняя
~2-4 недели
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

AI-агент для автоматизации браузера и веб-навигации

Разница между RPA-ботом и AI веб-агентом: RPA ломается при изменении верстки, AI-агент понимает семантику страницы. Вместо click("#submit-btn-v2") агент ищет кнопку с текстом «Оформить заказ» и находит её даже после редизайна.

Архитектура: Playwright + LLM

from playwright.async_api import async_playwright, Page
from anthropic import Anthropic
import asyncio
import base64
import json

client = Anthropic()

class AIWebAgent:

    def __init__(self, headless: bool = True):
        self.headless = headless

    async def run(self, task: str, start_url: str) -> str:
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=self.headless)
            context = await browser.new_context(
                viewport={"width": 1280, "height": 800},
                user_agent="Mozilla/5.0 (compatible; research-bot/1.0)"
            )
            page = await context.new_page()
            await page.goto(start_url)
            result = await self._agent_loop(page, task)
            await browser.close()
            return result

    async def _get_page_state(self, page: Page) -> dict:
        screenshot = await page.screenshot(type="png")
        screenshot_b64 = base64.standard_b64encode(screenshot).decode()

        elements = await page.evaluate("""() => {
            const interactive = document.querySelectorAll(
                'a, button, input, select, textarea, [role="button"]'
            );
            return Array.from(interactive).slice(0, 50).map((el, idx) => ({
                index: idx,
                tag: el.tagName.toLowerCase(),
                text: el.textContent?.trim().slice(0, 80) || '',
                type: el.type || '',
                placeholder: el.placeholder || '',
            }));
        }""")

        return {
            "url": page.url,
            "title": await page.title(),
            "screenshot": screenshot_b64,
            "elements": elements,
        }

    async def _execute_action(self, page: Page, action: dict) -> str:
        action_type = action.get("type")
        try:
            if action_type == "click":
                if "text" in action:
                    await page.get_by_text(action["text"]).first.click()
                elif "element_index" in action:
                    elements = await page.query_selector_all(
                        'a, button, input, select, textarea, [role="button"]'
                    )
                    if action["element_index"] < len(elements):
                        await elements[action["element_index"]].click()
            elif action_type == "fill":
                await page.fill(action["selector"], action["value"])
            elif action_type == "navigate":
                await page.goto(action["url"])
            elif action_type == "scroll":
                amount = action.get("amount", 500)
                direction = 1 if action.get("direction", "down") == "down" else -1
                await page.evaluate(f"window.scrollBy(0, {direction * amount})")
            elif action_type == "extract":
                return await page.evaluate(
                    f'document.querySelector({json.dumps(action.get("selector", "body"))})?.textContent?.trim()'
                )
            await asyncio.sleep(0.5)
            return "success"
        except Exception as e:
            return f"error: {e}"

    async def _agent_loop(self, page: Page, task: str) -> str:
        messages = []
        system = """Ты — AI веб-агент. Выполняй задачи в браузере.

Доступные действия (верни JSON):
- {"type": "click", "text": "текст кнопки"}
- {"type": "fill", "selector": "CSS", "value": "текст"}
- {"type": "navigate", "url": "https://..."}
- {"type": "scroll", "direction": "down", "amount": 500}
- {"type": "extract", "selector": ".result"}
- {"type": "done", "result": "итоговый результат"}

Формат ответа:
REASONING: <что видишь и что планируешь>
ACTION: <JSON с одним действием>"""

        for _ in range(20):
            state = await self._get_page_state(page)
            user_content = [
                {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": state["screenshot"]}},
                {"type": "text", "text": f"Задача: {task}\nURL: {state['url']}\nЭлементы:\n{json.dumps(state['elements'][:20], ensure_ascii=False)}"}
            ]
            messages.append({"role": "user", "content": user_content})

            response = client.messages.create(
                model="claude-opus-4-5",
                max_tokens=1024,
                system=system,
                messages=messages,
            )
            reply = response.content[0].text
            messages.append({"role": "assistant", "content": reply})

            try:
                action_line = [l for l in reply.split("\n") if l.startswith("ACTION:")][0]
                action = json.loads(action_line.replace("ACTION:", "").strip())
            except (IndexError, json.JSONDecodeError):
                continue

            if action.get("type") == "done":
                return action.get("result", "Task completed")

            await self._execute_action(page, action)

        return "Max iterations reached"

Конкурентный мониторинг цен

async def monitor_competitor_prices(products: list[str], sites: list[str]) -> dict:
    agent = AIWebAgent(headless=True)
    results = {}

    for product in products:
        task = f"Найди цену на '{product}', верни только число в рублях"
        for site in sites:
            price = await agent.run(task, f"https://{site}/search/?text={product}")
            results.setdefault(product, {})[site] = price

    return results

# Использование
prices = asyncio.run(monitor_competitor_prices(
    products=["Цемент М500 50кг", "Арматура 12мм 6м"],
    sites=["leroymerlin.ru", "obi.ru", "220-volt.ru"]
))

Обработка anti-bot защиты

async def setup_stealth_context(playwright):
    browser = await playwright.chromium.launch(
        headless=False,
        args=["--disable-blink-features=AutomationControlled"]
    )
    context = await browser.new_context(
        viewport={"width": 1366, "height": 768},
        locale="ru-RU",
        timezone_id="Europe/Moscow",
    )
    await context.add_init_script(
        "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
    )
    return context

Типовые применения

Мониторинг конкурентов — цены, акции, ассортимент на нескольких площадках автоматически каждый день.

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

Сбор отзывов — агрегация оценок и отзывов с нескольких площадок для анализа репутации.

Регрессионное тестирование UI — агент проходит пользовательские сценарии и фиксирует визуальные изменения.

Кейс: сеть строительных магазинов

Задача: ежедневный мониторинг цен 200 SKU у 5 конкурентов. Ручной процесс занимал 4 часа в день у менеджера по закупкам.

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

Результат: менеджер тратит 15 минут на анализ готового отчёта вместо 4 часов сбора данных. Реакция на изменение цен ускорилась с 1-2 дней до нескольких часов.

Сроки

  • Базовый агент для конкретного сайта: 3–5 дней
  • Универсальный агент с визуальным восприятием: 1–2 недели
  • Мониторинг цен с отчётами: 1 неделя
  • Anti-bot защита, ротация прокси: +1 неделя