Разработка бота для мониторинга отзывов товаров на маркетплейсах

Негативный отзыв на Ozon или Wildberries может висеть без ответа сутки. За это время он успевает оттолкнуть десятки потенциальных покупателей. Мы разработали бота, который сканирует отзывы в реальном времени и мгновенно уведомляет команду в Telegram. По нашим данным, 70% покупателей меняют мнение о

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка бота для мониторинга отзывов товаров на маркетплейсах
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1422
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    984
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1249
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    986
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    1000

Негативный отзыв на Ozon или Wildberries может висеть без ответа сутки. За это время он успевает оттолкнуть десятки потенциальных покупателей. Мы разработали бота, который сканирует отзывы в реальном времени и мгновенно уведомляет команду в Telegram. По нашим данным, 70% покупателей меняют мнение о бренде после быстрого ответа на негатив. Наш бот сокращает время реакции с часов до минут. За годы мы реализовали 30+ проектов по репутационному мониторингу — от простых парсеров до Enterprise-систем. Экономия времени на обработку отзывов достигает 40%.

Почему бот окупается за месяц?

Ручная проверка 1000 карточек товаров на нескольких площадках может занимать до 4 часов ежедневно. При стоимости часа оператора в X рублей ежемесячные затраты составляют десятки тысяч. Бот выполняет ту же работу за минуты и обходится в единоразовую инвестицию, которая окупается за 1–2 месяца за счёт снижения трудозатрат и повышения конверсии. В одном из проектов для крупного продавца электроники мы заменили ручной мониторинг 500 карточек на автоматизированный. Время реакции на негатив сократилось с 4 часов до 2 минут, а конверсия в лояльность выросла на 15%.

Бот быстрее ручного мониторинга

Ручная проверка десятков карточек товаров на нескольких площадках занимает часы. Бот проверяет каждую площадку по расписанию: для API-площадок — раз в час, для парсинга — раз в 4 часа. Уведомление приходит в Telegram за 1–2 минуты после появления отзыва. Это в 10–20 раз быстрее ручного подхода.

Параметр Ручной Автоматизированный
Время реакции на негатив 2–24 часа 1–5 минут
Количество проверяемых карточек в день до 50 неограниченно
Частота проверки 1 раз в день каждый час
Стоимость обслуживания высокая низкая

Как настроить бота за 3 шага?

  1. Подготовка источников. Вы передаёте список ссылок на товары или API-ключи (для Яндекс.Маркета). Мы создаём записи в review_sources.
  2. Запуск адаптеров. Бот запускает команды reviews:check --platform=... по расписанию. Каждый адаптер реализует интерфейс ReviewAdapterInterface и возвращает массив ReviewDTO.
  3. Настройка уведомлений. Указываете Telegram-чат для обычных отзывов и отдельный чат для срочных (негативных). Всё готово к работе.

Архитектура адаптеров для площадок

Каждая площадка — отдельный адаптер. Для платформ с API (Яндекс.Маркет) используем прямые запросы, для остальных — парсинг HTML через Playwright. Все адаптеры реализуют единый интерфейс ReviewAdapterInterface, что упрощает добавление новых площадок.

Схема данных включает две основные таблицы: review_sources (ссылки на товары) и reviews (сами отзывы). Индексы ускоряют выборку непрочитанных отзывов. Вот структура:

CREATE TABLE review_sources ( id BIGSERIAL PRIMARY KEY, platform VARCHAR(50) NOT NULL, -- 'yandex_market', 'ozon', 'google', 'otzovik' product_id BIGINT REFERENCES products(id), external_url TEXT NOT NULL, external_id VARCHAR(255), -- ID карточки на площадке scrape_config JSONB, is_active BOOLEAN DEFAULT TRUE, UNIQUE(platform, external_url) ); CREATE TABLE reviews ( id BIGSERIAL PRIMARY KEY, source_id BIGINT REFERENCES review_sources(id), external_id VARCHAR(255), -- ID отзыва на площадке author VARCHAR(255), rating SMALLINT, -- 1–5 text TEXT, pros TEXT, cons TEXT, published_at TIMESTAMP, discovered_at TIMESTAMP DEFAULT NOW(), sentiment VARCHAR(20), -- 'positive', 'negative', 'neutral' (ML) is_notified BOOLEAN DEFAULT FALSE, UNIQUE(source_id, external_id) ); CREATE INDEX idx_reviews_rating ON reviews(source_id, rating); CREATE INDEX idx_reviews_notified ON reviews(source_id) WHERE is_notified = FALSE; 

API или парсинг: сравнение

API стабильнее, но не у всех площадок открыт. Яндекс.Маркет предоставляет API партнёрам — без блокировок и с полными данными. Ozon и Wildberries API для отзывов не дают, поэтому используем Playwright: браузер рендерит страницу и извлекает отзывы. Это медленнее, но надёжно.

Вот сравнение подходов:

Характеристика API (Яндекс.Маркет) Парсинг (Ozon/WB)
Стабильность Высокая Средняя (зависит от структуры страницы)
Скорость Мгновенно 2–5 секунд на страницу
Полнота данных Все поля Ограничено HTML
Риск блокировки Нет Минимальный при разумных задержках

Адаптеры для Яндекс.Маркета и Ozon:

class YandexMarketReviewAdapter implements ReviewAdapterInterface { public function fetchReviews(ReviewSource $source): array { $modelId = $source->external_id; $response = Http::withHeaders([ 'Authorization' => 'Bearer ' . config('services.yandex_market.token'), ])->get("https://api.partner.market.yandex.ru/v2/models/{$modelId}/reviews", [ 'count' => 30, 'page' => 1, ]); return collect($response->json('result.reviews', [])) ->map(fn($r) => new ReviewDTO( externalId: (string) $r['id'], author: $r['author']['name'] ?? 'Аноним', rating: (int) $r['grade'], text: $r['text'] ?? '', pros: $r['pros'] ?? null, cons: $r['cons'] ?? null, publishedAt: Carbon::parse($r['date']), )) ->toArray(); } } class OzonReviewAdapter implements ReviewAdapterInterface { public function fetchReviews(ReviewSource $source): array { $data = $this->playwright->evaluate($source->external_url, <<<JS await page.waitForSelector('[data-widget="webReviewProductScore"]', {timeout: 10000}); const items = document.querySelectorAll('[data-widget="webSingleReview"]'); return Array.from(items).map(el => ({ id: el.dataset.reviewId, rating: parseInt(el.querySelector('[data-rating]')?.dataset.rating) || 0, text: el.querySelector('.review-text')?.textContent?.trim() || '', pros: el.querySelector('.pros')?.textContent?.trim() || null, cons: el.querySelector('.cons')?.textContent?.trim() || null, author: el.querySelector('.author-name')?.textContent?.trim() || 'Аноним', date: el.querySelector('time')?.getAttribute('datetime'), })); JS); return collect($data)->map(fn($r) => new ReviewDTO( externalId: $r['id'], author: $r['author'], rating: $r['rating'], text: $r['text'], pros: $r['pros'], cons: $r['cons'], publishedAt: $r['date'] ? Carbon::parse($r['date']) : now(), ))->toArray(); } } 

Механизм анализа тональности

Используем два уровня. Если рейтинг 1–2 или 4–5 — тональность очевидна. При рейтинге 3 запускаем анализ по ключевым словам или AI:

class SentimentAnalyzer { private array $negativeKeywords = [ 'брак', 'сломан', 'не работает', 'возврат', 'обман', 'разочарован', 'ужас', 'кошмар', 'мусор', 'дрянь', ]; private array $positiveKeywords = [ 'отлично', 'супер', 'доволен', 'рекомендую', 'превзошёл', 'быстро', 'качественно', 'спасибо', ]; public function analyze(ReviewDTO $review): string { if ($review->rating <= 2) return 'negative'; if ($review->rating >= 4) return 'positive'; $text = mb_strtolower($review->text . ' ' . $review->cons); foreach ($this->negativeKeywords as $kw) { if (str_contains($text, $kw)) return 'negative'; } return 'neutral'; } public function analyzeWithAI(string $text): string { $response = $this->openai->chat()->create([ 'model' => 'gpt-4o-mini', 'messages' => [ ['role' => 'system', 'content' => 'Определи тональность отзыва. Ответь одним словом: positive, negative или neutral.'], ['role' => 'user', 'content' => $text], ], 'max_tokens' => 10, ]); return in_array($response->choices[0]->message->content, ['positive', 'negative', 'neutral']) ? $response->choices[0]->message->content : 'neutral'; } } 

Уведомления отправляются в Telegram: для негативных отзывов — в отдельный чат срочной поддержки, для остальных — в общий. Сообщение содержит рейтинг, текст отзыва и ссылку.

class ReviewNotifier { public function notifyNew(Review $review): void { $emoji = match ($review->sentiment) { 'positive' => '⭐', 'negative' => '🚨', default => '💬', }; $stars = str_repeat('★', $review->rating) . str_repeat('☆', 5 - $review->rating); $text = "{$emoji} *Новый отзыв* — {$review->source->platform}\n" . "{$stars} {$review->rating}/5\n" . "*{$review->author}*\n\n" . mb_substr($review->text, 0, 300) . (mb_strlen($review->text) > 300 ? '...' : '') . "\n\n" . "[Открыть отзыв]({$review->source->external_url})"; $chatId = $review->sentiment === 'negative' ? config('telegram.urgent_reviews_chat') : config('telegram.reviews_chat'); $this->telegram->sendMessage([ 'chat_id' => $chatId, 'text' => $text, 'parse_mode' => 'Markdown', ]); $review->update(['is_notified' => true]); } } 

Аналитика рейтинга и расписание проверки:

-- Агрегат рейтинга по платформам за последние 30 дней SELECT rs.platform, COUNT(*) AS total_reviews, ROUND(AVG(r.rating), 2) AS avg_rating, COUNT(*) FILTER (WHERE r.rating <= 2) AS negative_count, COUNT(*) FILTER (WHERE r.rating >= 4) AS positive_count FROM reviews r JOIN review_sources rs ON r.source_id = rs.id WHERE r.published_at >= NOW() - INTERVAL '30 days' GROUP BY rs.platform ORDER BY avg_rating; -- Быстрые платформы с API — каждый час $schedule->command('reviews:check --platform=yandex_market')->hourly(); -- Парсинг через браузер — каждые 4 часа (ресурсоёмко) $schedule->command('reviews:check --platform=ozon')->everyFourHours(); $schedule->command('reviews:check --platform=wildberries')->everyFourHours(); -- Еженедельный сводный отчёт с трендом рейтинга $schedule->job(new WeeklyReviewsReportJob)->weekly()->mondays()->at('09:00'); 

Что делать, если площадка меняет HTML-структуру?

Парсинг зависим от вёрстки. При изменении селекторов адаптер перестаёт работать. Мы предусмотрели мониторинг: раз в сутки бот проверяет, что адаптер возвращает непустой результат. Если ошибка — уведомление в Telegram. Мы оперативно обновляем селекторы. В договоре фиксируем 2 недели пост-релизной поддержки, в течение которых адаптеры корректируются бесплатно.

Что входит в работу?

Проект под ключ включает: проектирование схемы данных, разработку адаптеров для трёх площадок, настройку расписания, реализацию анализа тональности, Telegram-уведомления, дашборд аналитики в админке. Сроки: базовая версия — 2 дня, полный комплект — до 5 рабочих дней. Стоимость рассчитывается индивидуально под ваш стек и количество площадок. Мы гарантируем стабильную работу бота при соблюдении лимитов площадок.

Свяжитесь с нами — оценим ваш проект за один рабочий день. Получите консультацию инженера.