
Корзина ВкусВилл
Автоматизация корзины ВкусВилл через browser-use CLI. Поиск товаров, добавление в корзину с правильными количествами, установка адреса доставки, получение ссылки на корзину. Предварительная проверка авторизации и адреса.
SKILL.md
Корзина ВкусВилл — browser-use
Автоматизируем добавление товаров в корзину на vkusvill.ru через browser-use CLI. Каждое действие — через реальный браузер: открываем страницы, ищем товары, добавляем в корзину.
Установка browser-use
Для работы этого навыка необходим browser-use.
Если browser-use не установлен — активируй навык browser-use и следуй его инструкциям. Он автоматически установит Python, pip и browser-use для твоей платформы.
Пока идёт установка, скажи: «Настраиваю корзину, это займёт пару минут...» НЕ показывай пользователю команды, ошибки или технические детали.
Если автоматическая установка не удалась — НЕ предлагай ручную альтернативу. Пробуй все варианты по порядку: pip → pip3 → установить Python (Windows: winget; macOS: brew; Linux: apt) → venv при permission denied → повторить. Пользователь не должен ничего делать вручную.
Требования (после установки)
browser-useCLI установлен и доступен на PATH- Аккаунт на vkusvill.ru (телефон + пароль или авторизация через соцсети)
- Для headed режима: дисплей или X11 forwarding
Проверка перед работой
ВЫПОЛНЯЙ ПЕРЕД КАЖДЫМ СЕАНСОМ. Это предотвращает 90% проблем.
# 1. Закрыть все старые сессии
browser-use close --all
sleep 1
# 2. Открыть ВкусВилл в headed режиме
browser-use --headed open https://vkusvill.ru
sleep 4
# 3. Проверить состояние страницы
browser-use state
Что проверять в state
-
Баннер cookies — если есть кнопка «Принять» / «Принять все» — нажми:
browser-use click <accept-cookies-index> sleep 1 -
Авторизация — проверь:
browser-use eval "!!document.querySelector('[class*=\"user\"], [class*=\"profile\"], [class*=\"account\"], .HeaderUser')"true→ пользователь авторизованfalse→ НЕОБХОДИМА АВТОРИЗАЦИЯ (см. ниже)
-
Адрес доставки — проверь наличие адреса в шапке:
browser-use eval "document.querySelector('[class*=\"address\"], [class*=\"AddressButton\"], [class*=\"delivery-address\"]')?.textContent?.trim()?.length > 3"true→ адрес установленfalse→ НАДО УСТАНОВИТЬ АДРЕС (см. ниже)
-
Промо-модалки — закрой любые всплывающие окна:
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"], [class*=\"Modal\"]').querySelector('[class*=\"close\"], [class*=\"Close\"], [aria-label=\"Закрыть\"]')?.click()" sleep 0.5
Авторизация
Если пользователь не авторизован, нужно попросить его войти вручную. Автоматизировать вход нельзя — это небезопасно и ненадёжно.
Попроси пользователя:
«Чтобы добавить товары в корзину, нужно войти в аккаунт ВкусВилл. Пожалуйста, авторизуйся в открывшемся окне браузера, а потом напиши "готово".»
Альтернатива — профиль браузера для сохранения сессии:
browser-use --profile "vv" --headed open https://vkusvill.ru
При первом запуске пользователь авторизуется. При последующих — сессия сохраняется.
Проверка после авторизации пользователем:
browser-use state
# Подождать и проверить снова
sleep 3
browser-use eval "!!document.querySelector('[class*=\"user\"], [class*=\"profile\"], [class*=\"account\"], .HeaderUser')"
Установка адреса доставки
Адрес ОБЯЗАТЕЛЕН для добавления товаров в корзину. Без него кнопка «В корзину» может не работать или товары добавятся в «отложенные».
Пошаговая установка адреса
# 1. Нажать на кнопку адреса в шапке
# Ищем элемент с классом содержащим "address" или "AddressButton"
browser-use state
# Найти индекс кнопки адреса и нажать
browser-use click <address-button-index>
sleep 2
# 2. В модалке адресов нажать "Добавить новый адрес"
browser-use state
# Найти кнопку "Добавить новый адрес" / "Новый адрес"
browser-use click <add-address-index>
sleep 1
# 3. Ввести адрес в поле ввода
browser-use state
# Найти поле ввода адреса
browser-use click <address-input-index>
browser-use type "<адрес пользователя>"
sleep 1
# 4. Выбрать подсказку из выпадающего списка
browser-use state
# Найти подходящую подсказку (первую или наиболее точную)
browser-use click <suggestion-index>
sleep 1
# 5. Подтвердить выбор — нажать "Выбрать" / "Сохранить"
browser-use state
browser-use click <confirm-address-index>
sleep 2
# 6. Выбрать время доставки (если появится)
browser-use state
# Если открылась панель времени — выбрать ближайший слот
browser-use click <time-slot-index>
sleep 1
Если адрес не устанавливается:
- Возможно адрес вне зоны доставки — сообщи пользователю
- Попробуй другой формат адреса (улица → проспект)
- VkusVill работает не во всех городах — проверь
Структура сайта ВкусВилл
URL-паттерны
| Действие | URL |
|---|---|
| Главная | https://vkusvill.ru |
| Поиск товара | https://vkusvill.ru/search/?q=<запрос> |
| Корзина | https://vkusvill.ru/cart/ или https://vkusvill.ru/basket/ |
| Каталог | https://vkusvill.ru/catalog/ |
| Конкретная категория | https://vkusvill.ru/catalog/<category-slug>/ |
Карточка товара
┌─────────────────────────────────────────┐
│ ┌───────┐ │
│ │ │ Название товара │
│ │ Фото │ .ProductCard__name │
│ │ │ .GoodsCard__name │
│ └───────┘ │
│ │
│ Вес/объём: 500г │
│ .ProductCard__weight │
│ │
│ XXX ₽ [ - ] [ 1 ] [ + ] [🛒+] │
│ .ProductCard__price .CartButton │
└─────────────────────────────────────────┘
Ключевые селекторы
| Элемент | CSS селектор |
|---|---|
| Карточка товара | .ProductCard, .GoodsCard, [class*="product-card"] |
| Название товара | .ProductCard__name, .GoodsCard__name, [class*="product-name"] |
| Цена | .ProductCard__price, .GoodsCard__price, [class*="price"] |
| Вес/объём | .ProductCard__weight, .GoodsCard__weight, [class*="weight"] |
| Кнопка «В корзину» | [class*="add-to-cart"], [class*="AddButton"], кнопка с иконкой корзины |
| Поле количества | [class*="quantity"] input, [class*="Quantity"] input |
| Кнопка «+» | [class*="quantity-up"], [class*="QuantityUp"] |
| Кнопка «−» | [class*="quantity-down"], [class*="QuantityDown"] |
| Счётчик корзины | [class*="cart-count"], [class*="CartCount"], .HeaderCart__count |
| Кнопка адреса | [class*="address"], [class*="AddressButton"] |
| Поле ввода адреса | [class*="address-input"], input[placeholder*="адрес"] |
| Подсказки адреса | [class*="suggest"], [class*="Suggest"] |
| Модальное окно | [class*="modal"], [class*="Modal"], [class*="popup"] |
| Закрыть модалку | [class*="modal"] [class*="close"], [aria-label="Закрыть"] |
| Кнопка «Поделиться» | button.shareBasket, [class*="share"], кнопка с текстом «Поделиться» |
| Товар в корзине | .ProductCard, .cart-item, [class*="basket-product"] |
| Итог корзины | [class*="total"], .DeliveryBasket__total, [class*="BasketTotal"] |
Добавление товара в корзину
Основной алгоритм
Для каждого товара из списка:
# 1. Открыть страницу поиска
browser-use open "https://vkusvill.ru/search/?q=<название_товара>"
sleep 3
# 2. Закрыть модалки если появились
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]')?.click()"
sleep 0.5
# 3. Проверить что товары загрузились
browser-use eval "document.querySelectorAll('.ProductCard, .GoodsCard, [class*=\"product-card\"]').length"
# Если 0 — товар не найден, попробовать другой запрос
# 4. Прочитать первый товар
browser-use eval "const c = document.querySelector('.ProductCard, .GoodsCard, [class*=\"product-card\"]'); JSON.stringify({name: c?.querySelector('.ProductCard__name, .GoodsCard__name, [class*=\"product-name\"]')?.textContent?.trim(), price: c?.querySelector('.ProductCard__price, .GoodsCard__price, [class*=\"price\"]')?.textContent?.trim(), weight: c?.querySelector('.ProductCard__weight, .GoodsCard__weight, [class*=\"weight\"]')?.textContent?.trim()})"
# 5. Получить state для определения индексов кнопок
browser-use state
# 6. Нажать кнопку «В корзину» на первом товаре
# Найти индекс кнопки добавления в state и нажать
browser-use click <add-to-cart-button-index>
sleep 1
# 7. Если нужно количество > 1 — установить количество (см. ниже)
Установка количества
После первого нажатия «В корзину» появляются контролы количества.
# Определить тип товара (весовой или штучный)
browser-use eval "const input = document.querySelector('[class*=\"quantity\"] input, [class*=\"Quantity\"] input'); input ? (input.className.includes('_kg') ? 'weight' : 'pieces') : 'unknown'"
# ВАРИАНТ A: Товар весовой (кг) — вводим килограммы
# Например: 0.4 кг = 400г
browser-use state
browser-use click <quantity-input-index>
# Сначала очистить поле
browser-use keys "Control+a"
browser-use type "0.4"
browser-use keys "Enter"
sleep 0.5
# ВАРИАНТ B: Товар штучный (шт) — вводим количество
browser-use state
browser-use click <quantity-input-index>
browser-use keys "Control+a"
browser-use type "3"
browser-use keys "Enter"
sleep 0.5
# ВАРИАНТ C: Если input не находится — использовать кнопку "+"
# Нажать + нужное количество раз (для N штук нажать N-1 раз)
browser-use click <plus-button-index>
sleep 0.2
browser-use click <plus-button-index>
sleep 0.2
Весовые товары: продвинутые тактики
На vkusvill.ru весовые товары добавляются с дефолтным весом (обычно 0.85 кг). Контрол количества часто реализован как <span>, а не <input> — стандартный browser-use type не работает. Минус-кнопка может сбрасывать товар в 0 вместо уменьшения.
Пробуй тактики по порядку — переходи к следующей, если предыдущая не сработала:
Тактика 1: React-стейт через REACT_INTERNALS
# Попробовать добраться до React fiber и установить значение напрямую
browser-use eval "
const span = document.querySelector('[class*=\"weight\"], [class*=\"Weight\"], [class*=\"quantity\"] span');
const key = Object.keys(span).find(k => k.startsWith('__reactInternalInstance') || k.startsWith('__reactFiber'));
if (key) {
const fiber = span[key];
const props = fiber.memoizedProps || fiber.pendingProps;
if (props && props.onChange) {
props.onChange({target: {value: '0.4'}});
'react_fiber_ok';
} else { 'no_onchange'; }
} else { 'no_fiber'; }
"
Тактика 2: Клик на <span> с весом + клавиатурный ввод
# Кликнуть на span с весом (активирует inline-редактирование)
browser-use state
# Найти индекс <span> с текущим весом (например "0.85") и кликнуть
browser-use click <weight-span-index>
sleep 0.3
# Выделить всё и ввести нужный вес
browser-use keys "Control+a"
browser-use type "0.4"
browser-use keys "Enter"
sleep 0.5
# Проверить что вес изменился
browser-use eval "document.querySelector('[class*=\"weight\"], [class*=\"Weight\"]')?.textContent?.match(/[\\d.]+/)?.[0]"
Тактика 3: Кнопки «+»/«−» с проверкой шага
# 1. Запомнить текущий вес
browser-use eval "document.querySelector('[class*=\"weight\"], [class*=\"Weight\"]')?.textContent?.trim()"
# 2. Нажать «−» ОДИН раз
browser-use click <minus-button-index>
sleep 0.5
# 3. Проверить новый вес — понять шаг
browser-use eval "document.querySelector('[class*=\"weight\"], [class*=\"Weight\"]')?.textContent?.trim()"
# 4. Если шаг адекватный (например 0.1 кг) — повторять «−» или «+» до нужного веса
# Если шаг = весь вес (сбросило в 0) — ЭТА ТАКТИКА НЕ РАБОТАЕТ, переходи к тактике 4
Тактика 4: Fallback — дефолтный вес + корректировки
Если ни одна из тактик не сработала:
- Добавь товар с дефолтным весом
- Запиши в список «корректировок»:
⚠️ Корректировки веса (измени вручную в корзине): - «Филе минтая» — добавлено 0.85 кг, нужно 0.4 кг - «Шампиньоны» — добавлено 0.85 кг, нужно 0.5 кг - Сообщи пользователю: «Добавил [товар] с весом по умолчанию (0.85 кг). Нужно [X] кг — скорректируй в корзине, пожалуйста.»
- Собери все корректировки и выведи единым списком в конце
Определение фасовки
Некоторые товары продаются упаковками (упак) или поштучно (шт). Проверяй текст карточки:
browser-use eval "const c = document.querySelector('.ProductCard, .GoodsCard, [class*=\"product-card\"]'); const t = c?.textContent || ''; const m = t.match(/(\\d+)\\s*(шт|упак|уп)/i); m ? m[0] : 'single'"
«6 шт»→ в упаковке 6 штук. Если нужно 6 штук → добавить 1 упаковку.«1 упак»→ минимальная единица = 1 упаковка.single→ поштучный или весовой.
Стратегия поиска
Если товар не найден по первому запросу:
- Упрощённый запрос: «Филе куриной грудки» → «куриная грудка»
- Общий запрос: «Творог 5% ВкусВилл» → «творог»
- Замена из таблицы замен (см. shopping-list, секция «Замены и альтернативы»): при 0 результатах автоматически попробуй первый вариант замены, потом второй (до 2 попыток)
- Категория: перейти в каталог → раздел → подкатегорию
- Сообщить пользователю: «Не нашёл [товар], добавлю ближайший аналог: [название]»
Проверка корзины
После добавления всех товаров:
# 1. Перейти в корзину
browser-use open "https://vkusvill.ru/cart/"
sleep 3
# 2. Закрыть модалки
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]')?.click()"
sleep 0.5
# 3. Получить содержимое корзины
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('.ProductCard, .cart-item, [class*=\"basket-product\"]')).map(el => ({name: el.querySelector('.ProductCard__name, .GoodsCard__name, [class*=\"product-name\"]')?.textContent?.trim(), qty: el.querySelector('[class*=\"quantity\"], [class*=\"Quantity\"], [class*=\"CartButton__quantity\"]')?.textContent?.trim(), price: el.querySelector('.ProductCard__price, .GoodsCard__price, [class*=\"price\"]')?.textContent?.trim()})).filter(i => i.name && i.name.length > 2))"
# 4. Получить итоговую сумму
browser-use eval "document.querySelector('[class*=\"total\"], .DeliveryBasket__total, [class*=\"BasketTotal\"]')?.textContent?.trim()"
# 5. Проверить количество товаров
browser-use eval "document.querySelectorAll('.ProductCard, .cart-item, [class*=\"basket-product\"]').length"
Batch add mode (для списков 10+ товаров)
Когда нужно добавить много товаров (20+), поштучный search → state → click занимает 15-20 минут. Batch mode сокращает время в 3-4 раза.
Принцип
- Раздели товары на штучные (упак/шт) и весовые (кг)
- Штучные — добавляй батчем через один eval
- Весовые — обрабатывай отдельно после батча
Штучные товары: batch-добавление
# 1. Открыть страницу поиска для товара
browser-use open "https://vkusvill.ru/search/?q=<товар>"
sleep 3
# 2. Закрыть модалки
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]')?.click()"
sleep 0.3
# 3. Проверить что есть карточки
browser-use eval "document.querySelectorAll('.ProductCard, .GoodsCard, [class*=\"product-card\"]').length"
# Если 0 — пробуй замену из таблицы замен (см. shopping-list)
# 4. Кликнуть «В корзину» на первом товаре (eval быстрее чем state + click)
browser-use eval "
const btn = document.querySelector('[class*=\"add-to-cart\"], [class*=\"AddButton\"], button[class*=\"cart\"]') || document.querySelector('.ProductCard button, .GoodsCard button');
if (btn) { btn.click(); 'clicked'; } else { 'no_button'; }
"
sleep 1
# 5. Если нужно количество > 1 — добавить через кнопку «+»
# НЕ делать state после каждого клика! Только eval для проверки
browser-use eval "
const plus = document.querySelector('[class*=\"quantity-up\"], [class*=\"QuantityUp\"], button[aria-label*=\"плюс\"]');
if (plus) { for(let i = 0; i < 2; i++) plus.click(); 'added_2'; } else { 'no_plus'; }
"
sleep 0.5
Оптимизация: НЕ делай state на каждой странице
Для штучных товаров, когда структура страницы уже известна:
- Первые 3 товара — делай
stateдля проверки - После этого — используй только
evalдля клика и проверки - Делай
stateтолько при сбоях или если DOM не реагирует
# Быстрая проверка вместо полного state
# Товары загрузились?
browser-use eval "document.querySelectorAll('[class*=\"product-card\"], .ProductCard').length"
# Добавился?
browser-use eval "document.querySelector('[class*=\"cart-count\"], .HeaderCart__count')?.textContent?.trim()"
Чекпоинты при добавлении в корзину
При добавлении 10+ товаров сохраняй прогресс каждые 10 позиций.
Формат cart-progress.md
---
status: in_progress
total_items: 48
added_items: 10
last_item: "Творог 5%"
cart_total: "~2 800 ₽"
started: "2026-06-05 14:30"
---
## Добавленные товары
1. ~~Филе куриной грудки~~ ✓
2. ~~Гречка~~ ✓
...
10. ~~Творог 5%~~ ✓
## Оставшиеся товары
11. Сыр твёрдый
12. Помидоры
...
## Корректировки веса
(пусто)
Когда сохранять
- Каждые 10 добавленных товаров
- При замене товара (запиши что заменили и на что)
- При ошибке, требующей внимания пользователя
При старте сессии
- Проверь наличие
cart-progress.mdв памяти агента - Если
status: in_progress→ спроси: «У тебя осталась незавершённая корзина (добавлено X из Y). Продолжить с того места?» - Если «да» — пропускай уже добавленные товары
- Если «нет» — начни с начала, обнови файл
При завершении
Обнови status: done в cart-progress.md.
Получение ссылки на корзину
browser-use eval может обрезать длинные строки (truncation). Ссылка «Поделиться» обычно длинная (>80 символов). Используй пошаговую стратегию:
# 1. Убедиться что мы в корзине
browser-use open "https://vkusvill.ru/cart/"
sleep 3
# 2. Закрыть модалки
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]')?.click()"
sleep 0.5
# 3. Найти и нажать кнопку «Поделиться»
browser-use state
browser-use click <share-button-index>
sleep 1
# 4. Попытка получить ссылку целиком
browser-use eval "document.querySelector('input[type=\"text\"][value*=\"vkusvill.ru\"]')?.value"
# 5. Если truncated — измерить длину
browser-use eval "document.querySelector('input[type=\"text\"][value*=\"vkusvill.ru\"]')?.value?.length"
# 6. Если длина > 80 — получить по частям
browser-use eval "const v = document.querySelector('input[type=\"text\"][value*=\"vkusvill.ru\"]')?.value; v ? v.substring(0, 60) : null"
browser-use eval "const v = document.querySelector('input[type=\"text\"][value*=\"vkusvill.ru\"]')?.value; v ? v.substring(60) : null"
# 7. Fallback — вернуть URL корзины
browser-use eval "document.URL"
# И сказать: «Ссылка получена, но для шаринга нажми кнопку "Поделиться" в корзине»
Полный workflow: добавление списка товаров
# === PRE-FLIGHT ===
browser-use close --all
sleep 1
browser-use --headed open https://vkusvill.ru
sleep 4
# Проверить авторизацию
browser-use eval "!!document.querySelector('[class*=\"user\"], [class*=\"profile\"], [class*=\"account\"], .HeaderUser')"
# Если false → ПОПРОСИТЬ ПОЛЬЗОВАТЕЛЯ АВТОРИЗОВАТЬСЯ
# Закрыть модалки
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]')?.click()"
# Проверить адрес
browser-use eval "document.querySelector('[class*=\"address\"], [class*=\"AddressButton\"]')?.textContent?.trim()?.length > 3"
# Если false → УСТАНОВИТЬ АДРЕС
# === ПРОВЕРИТЬ ЧЕКПОИНТ ===
# Если есть cart-progress.md со status: in_progress → предложить продолжить
# === BATCH: ШТУЧНЫЕ ТОВАРЫ ===
# Для каждого штучного товара (без state на каждой странице):
browser-use open "https://vkusvill.ru/search/?q=<товар>"
sleep 3
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"]')?.click()"
browser-use eval "document.querySelectorAll('[class*=\"product-card\"]').length" # > 0?
browser-use eval "document.querySelector('[class*=\"add-to-cart\"], [class*=\"AddButton\"]')?.click() || 'no_btn'"
sleep 1
# НЕ делать state! Только eval для проверки
# ЧЕКПОИНТ каждые 10 товаров
# === ВЕСОВЫЕ ТОВАРЫ (отдельно, после батча) ===
# Для каждого весового товара — полный алгоритм с тактиками из секции выше
# === VERIFY CART ===
browser-use open "https://vkusvill.ru/cart/"
sleep 3
browser-use eval "document.querySelectorAll('.ProductCard, .cart-item, [class*=\"basket-product\"]').length"
# === SHARE LINK ===
# (см. секцию «Получение ссылки на корзину» с обработкой truncation)
Обработка ошибок
| Проблема | Решение |
|---|---|
| Товар не найден (0 карточек) | Упрости запрос. Попробуй синоним. Сообщи пользователю. |
| Модалка блокирует действия | eval чтобы кликнуть close. Или Escape. |
| Кнопка «В корзину» не нажимается | Проверь адрес доставки — без адреса кнопка может не работать |
| Количество не вводится | Попробуй кнопку «+». Если и она не работает — товар может быть unavailable |
| Корзина пустая после добавления | Проверь авторизацию. Без логина корзина не сохраняется. |
| Ссылка «Поделиться» не найдена | Верни URL корзины. Ссылка может быть недоступна в некоторых регионах. |
| Страница долго грузится | Увеличь sleep до 5 секунд. VkusVill — тяжёлый SPA. |
| «Element not found» после навигации | DOM перерисовался — запусти state заново для свежих индексов. |
| Сессия зависла | browser-use close --all, начни заново. |
| Неверный товар добавлен | Перейди в корзину, удали (кнопка «−» до 0 или «Удалить»), и повтори поиск с уточнённым запросом. |
JavaScript Eval Snippets
# Проверить авторизацию
browser-use eval "!!document.querySelector('[class*=\"user\"], [class*=\"profile\"], .HeaderUser')"
# Посчитать товары в выдаче поиска
browser-use eval "document.querySelectorAll('.ProductCard, .GoodsCard, [class*=\"product-card\"]').length"
# Получить название первого товара
browser-use eval "document.querySelector('.ProductCard__name, .GoodsCard__name, [class*=\"product-name\"]')?.textContent?.trim()"
# Получить цену первого товара
browser-use eval "document.querySelector('.ProductCard__price, .GoodsCard__price, [class*=\"price\"]')?.textContent?.trim()"
# Проверить наличие адреса
browser-use eval "document.querySelector('[class*=\"address\"], [class*=\"AddressButton\"]')?.textContent?.trim()?.substring(0, 50)"
# Счётчик товаров в корзине (в шапке)
browser-use eval "document.querySelector('[class*=\"cart-count\"], [class*=\"CartCount\"], .HeaderCart__count')?.textContent?.trim()"
# Закрыть все модалки
browser-use eval "document.querySelectorAll('[class*=\"modal\"], [class*=\"popup\"], [class*=\"Modal\"]').forEach(m => { const c = m.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]'); if(c) c.click(); })"
Оптимизация: не злоупотребляй state
browser-use state дампит весь DOM. VkusVill SPA рендерит 5000+ px — state тормозит 10-30 секунд и забивает контекст.
Правила
- Делай
stateтолько: в начале сессии, при смене структуры страницы, при сбоях - НЕ делай
stateна каждой странице поиска если уже знаешь структуру - Используй
evalдля точечных проверок вместо полногоstate
Быстрые eval-сниппеты для типовых проверок
# Есть ли карточки товаров?
browser-use eval "document.querySelectorAll('[class*=\"product-card\"], .ProductCard, .GoodsCard').length"
# Название первого товара
browser-use eval "document.querySelector('[class*=\"product-name\"], .ProductCard__name, .GoodsCard__name')?.textContent?.trim()"
# Цена первого товара
browser-use eval "document.querySelector('[class*=\"price\"]')?.textContent?.trim()?.substring(0, 30)"
# Какой текст у N-й кнопки?
browser-use eval "document.querySelectorAll('button')[N]?.textContent?.trim()"
# Сколько товаров в корзине (счётчик в шапке)?
browser-use eval "document.querySelector('[class*=\"cart-count\"], .HeaderCart__count')?.textContent?.trim()"
# Добавился ли товар? (проверить что счётчик увеличился)
browser-use eval "document.querySelector('[class*=\"cart-count\"], .HeaderCart__count')?.textContent?.trim()"
Советы
- Всегда
close --allпервым — устаревшие сессии — причина #1 зависаний. - Жди после навигации — VkusVill — тяжёлый SPA.
sleep 3-4послеopen. - Проверяй модалки перед каждым действием — они появляются непредсказуемо.
- Не переиспользуй индексы — после любого действия DOM меняется, делай
stateзаново. - Адрес — обязателен — без адреса корзина работает некорректно.
- Авторизация — обязательна — без логина товары не сохраняются.
- Упрощай запросы — «Филе куриной грудки ВкусВилл» → «куриная грудка».
- Проверяй корзину в конце — убедись что все товары добавлены.
- Используй
--profile— для сохранения сессии между запусками:browser-use --profile "vv" --headed open https://vkusvill.ru
Cleanup
browser-use close # закрыть текущую сессию
browser-use close --all # закрыть ВСЕ сессии (использовать между задачами)
Ресурсы (1)
root/