Як бот для моніторингу нових товарів допомагає випередити конкурентів?
Ручний перегляд каталогів конкурентів забирає години щодня. Замість того, щоб зосередитися на стратегії, ви змушені відкривати десятки сторінок, вишукуючи нові позиції. Один конкурент з 20 категоріями та 50 сторінками каталогу забирає близько 30–40 хвилин на день. При 5–10 конкурентах це перетворюється на повноцінну робочу зміну, а людський фактор неминуче призводить до пропуску 20–30% новинок.
Ми автоматизуємо цей процес. Наш бот щодня сканує сторінки товарів за заданими розкладами та миттєво сповіщає вас про новинки через Telegram. Ви отримуєте лише реальні зміни, без шуму. Це дозволяє реагувати швидше за конкурентів та не втрачати аудиторію.
За 5+ років роботи ми розробили рішення для 40+ інтернет-магазинів, від невеликих нішевих проєктів до великих маркетплейсів. Наш досвід гарантує стабільну роботу навіть при зміні верстки конкурента — ми використовуємо семантичні селектори та fallback-стратегії. Економія часу на моніторинг — до 80%. Бот обробляє до 10 000 SKU на день, генеруючи звіти в реальному часі.
Чому ручний моніторинг неефективний?
У конкурентів сотні сторінок каталогу, і вони оновлюються щодня. Переглядати їх вручну — втрачати час та пропускати новинки. Бот перевіряє кожну сторінку за розкладом, і ви дізнаєтеся про нові товари за хвилини.
Крім того, людське око не здатне одночасно відстежувати десятки категорій. Пропуски неминучі, особливо якщо товар з'являється в середині списку. Бот же фіксує кожну зміну, порівнюючи поточний стан з еталонним знімком.
Як бот виявляє нові товари?
Моніторинг нових товарів відрізняється від моніторингу цін. Ми стежимо не за конкретним URL, а за розділами каталогу — категоріями, сторінками "Новинки", результатами пошуку. Алгоритм виглядає так:
Конфігурація (URL каталогу + селектор) → Scraper → Snapshot → Diff → Alert
- Scraper завантажує сторінку та витягує список товарів за CSS-селекторами.
- Кожен товар зберігається в БД з хешем полів.
- При повторному скануванні новий список порівнюється з попереднім.
- Відсутні в старому знімку позиції позначаються як новинки.
- Система надсилає сповіщення в Telegram.
Детальний алгоритм роботи детектора
Для кожного конкурента налаштовується JSON-конфіг із селекторами та правилами пагінації:
{
"pagination": {
"type": "url_param",
"param": "page",
"max_pages": 20
},
"item_selector": ".catalog-item",
"fields": {
"url": {"selector": "a.product-link", "attr": "href"},
"title": {"selector": ".product-name", "text": true},
"sku": {"selector": "[data-sku]", "attr": "data-sku"},
"price": {"selector": ".price", "text": true},
"image": {"selector": "img.product-image", "attr": "src"}
}
}
Схема даних для зберігання знімків та новинок:
CREATE TABLE competitor_catalogs (
id BIGSERIAL PRIMARY KEY,
competitor_id INT REFERENCES competitors(id),
url TEXT NOT NULL,
scrape_config JSONB NOT NULL,
check_interval INTERVAL DEFAULT '6 hours',
last_checked_at TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE
);
CREATE TABLE competitor_items (
id BIGSERIAL PRIMARY KEY,
catalog_id BIGINT REFERENCES competitor_catalogs(id),
external_url TEXT NOT NULL,
title TEXT,
external_sku VARCHAR(255),
price NUMERIC(12,2),
image_url TEXT,
first_seen_at TIMESTAMP DEFAULT NOW(),
last_seen_at TIMESTAMP DEFAULT NOW(),
is_new BOOLEAN DEFAULT TRUE,
UNIQUE(catalog_id, external_url)
);
CREATE INDEX idx_competitor_items_new
ON competitor_items(catalog_id, first_seen_at)
WHERE is_new = TRUE;
Сам скрапер реалізовано на PHP з використанням Symfony DomCrawler:
class CatalogScraper
{
public function scrape(CompetitorCatalog $catalog): array
{
$config = $catalog->scrape_config;
$items = [];
$maxPages = $config['pagination']['max_pages'] ?? 1;
for ($page = 1; $page <= $maxPages; $page++) {
$url = $this->buildPageUrl($catalog->url, $config['pagination'], $page);
$html = $this->fetchWithRetry($url);
if (!$html) break;
$pageItems = $this->extractItems($html, $config);
if (empty($pageItems)) break;
$items = array_merge($items, $pageItems);
usleep(rand(1_500_000, 3_000_000));
}
return $items;
}
private function extractItems(string $html, array $config): array
{
$crawler = new \Symfony\Component\DomCrawler\Crawler($html);
$items = [];
$crawler->filter($config['item_selector'])->each(function ($node) use ($config, &$items) {
$item = [];
foreach ($config['fields'] as $field => $fieldConfig) {
try {
$el = $node->filter($fieldConfig['selector'])->first();
if ($el->count() === 0) continue;
$item[$field] = isset($fieldConfig['attr'])
? $el->attr($fieldConfig['attr'])
: $el->text();
} catch (\Exception $e) {
continue;
}
}
if (!empty($item['url'])) {
$items[] = $item;
}
});
return $items;
}
}
Сервіс виявлення новинок:
class NewProductDetectionService
{
public function process(CompetitorCatalog $catalog): DetectionResult
{
$scraped = $this->scraper->scrape($catalog);
$newItems = [];
foreach ($scraped as $item) {
$url = $this->normalizeUrl($item['url'], $catalog->url);
$existing = CompetitorItem::where([
'catalog_id' => $catalog->id,
'external_url' => $url,
])->first();
if (!$existing) {
$created = CompetitorItem::create([
'catalog_id' => $catalog->id,
'external_url' => $url,
'title' => $item['title'] ?? null,
'external_sku' => $item['sku'] ?? null,
'price' => $this->parsePrice($item['price'] ?? ''),
'image_url' => $item['image'] ?? null,
'is_new' => true,
]);
$newItems[] = $created;
} else {
$existing->update(['last_seen_at' => now()]);
}
}
$disappeared = CompetitorItem::where('catalog_id', $catalog->id)
->where('last_seen_at', '<', now()->subDays(3))
->get();
$catalog->update(['last_checked_at' => now()]);
return new DetectionResult(newItems: $newItems, disappeared: $disappeared);
}
}
Після виявлення новинок бот надсилає повідомлення в Telegram з короткою інформацією: назва, ціна, посилання. Сповіщення надходять протягом хвилини після сканування.
Обхід захисту від ботів
| Захист | Метод обходу |
|---|---|
| Cloudflare Bot Management | Playwright + stealth plugin |
| Rate limiting | Випадкові затримки 2–5 сек між запитами |
| IP-блокування | Ротація проксі (residential proxies) |
| Вимога cookies/сесії | Headless-браузер із збереженням сесії |
| JS-рендеринг | Playwright/Puppeteer замість curl |
Що входить в роботу
- Конфігурація до 5 конкурентів (категорії, селектори, інтервали)
- Налаштування Telegram-сповіщень (новинки, зникнення)
- Розгортання на вашому сервері (Docker-образ)
- Документація з експлуатації
- Навчання команди (1 година)
- Підтримка та доопрацювання протягом 1 місяця
Порівняння підходів
| Параметр | Ручний моніторинг | Бот |
|---|---|---|
| Час на перевірку 1 конкурента | 30 хв/день | 1 сек/день |
| Пропуск новинок | до 30% | <1% |
| Реакція на зміни | години–дні | хвилини |
| Витрати на масштабування | лінійні | фіксовані |
Типові помилки при моніторингу та як їх уникнути
-
Ігнорування пагінації. Якщо у конкурента більше однієї сторінки, бот пройде по всіх. Перевірте налаштування
max_pages. - Занадто часті запити. Ризик блокування. Рекомендуємо інтервал 6–12 годин.
- Жорсткі селектори. При зміні верстки селектор може зламатися. Використовуйте data-атрибути або класи-ідентифікатори.
- Відсутність обробки помилок. Якщо сторінка тимчасово недоступна, бот повинен повторювати спробу із затримкою.
Терміни реалізації
- CatalogScraper + конфігурація через JSON: 1–2 дні
- NewProductDetectionService + схема даних: 1 день
- Сповіщення Telegram: 0.5 дня
- Playwright-адаптер для JS-сайтів: +1 день
- Ротація проксі: +0.5 дня
Разом: 3–4 робочих дні.
Отримайте консультацію з автоматизації моніторингу — це безкоштовно. Наші інженери проведуть аудит ваших конкурентів та запропонують оптимальне рішення.
Зв'яжіться з нами, щоб обговорити ваше завдання. Ми оцінимо проєкт і підберемо конфігурацію під ваш бюджет.







