Розробка бота-парсера акцій та знижок конкурентів

Уявіть: ваш головний конкурент запустив флеш-розпродаж зі знижкою 40% на популярний товар, а ви дізналися про це через два дні, коли клієнти вже пішли до нього. Регулярний ручний моніторинг знижок забирає години роботи маркетолога, при цьому легко пропустити раптову акцію. Наш бот для відстеження ак

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, 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

Уявіть: ваш головний конкурент запустив флеш-розпродаж зі знижкою 40% на популярний товар, а ви дізналися про це через два дні, коли клієнти вже пішли до нього. Регулярний ручний моніторинг знижок забирає години роботи маркетолога, при цьому легко пропустити раптову акцію. Наш бот для відстеження акцій знаходить акції в 10 разів швидше ручного моніторингу — інформація про нову акцію надходить за хвилини, а не за години. Ми розробляємо ботів-парсерів, які цілодобово сканують сторінки акцій ваших конкурентів, витягують умови, промокоди та терміни, і миттєво сповіщають вас через Slack або Telegram. Наша команда має досвід, виконала понад 50 проектів з автоматизації конкурентного аналізу. Ми надаємо гарантію якості на 30 днів після деплою, а всі розробники сертифіковані за стандартами PHP. Один з кейсів: інтернет-магазин електроніки після впровадження нашого рішення скоротив час реакції на акції конкурента з 2 днів до 2 годин, а щотижнева економія людино-годин склала понад 15. Окупність рішення — менше двох місяців. Вартість базового парсера для 3–5 конкурентів — від $2000, а щомісячна економія на ручному моніторингу може сягати $3000. Парсер побудований на PHP 8.3 та Laravel 11 з використанням DomCrawler, дані зберігаються в PostgreSQL. Автоматизація скорочує витрати часу в 5 разів порівняно з ручним аналізом. Ми пропонуємо аналіз конкурентних акцій із точністю 95%. Наш парсер краще за ручний моніторинг у 10 разів за швидкістю.

Як парсер акцій допомагає виграти в конкурентів?

Ручний моніторинг знижок не справляється з динамікою акцій: знижки змінюються щогодини, промокоди мають обмежений термін дії, а структура сторінок відрізняється від сайту до сайту. Парсинг промокодів — одна з ключових функцій. Типові складнощі: акції з різними типами знижок (відсоток, фіксована ціна, промокод) вимагають різних методів вилучення; дати початку та закінчення часто приховані в тексті або вказані в нестандартному форматі; промокоди можуть бути закодовані або заховані в HTML. Парсер вирішує всі ці проблеми: він шукає структуровані блоки (.promotion-card, .sale-block) і при їх відсутності аналізує текст за допомогою регулярних виразів. Наприклад, якщо дата вказана як «до кінця тижня», парсер обчислює точну дату за календарем; якщо промокод з'являється тільки після кліку, емулюється дія через headless-браузер.

Які проблеми вирішує парсер акцій?

Ціни змінюються рідше та передбачуваніше, а акції — потужний інструмент залучення трафіку. Автоматичний моніторинг цін також підтримується, але акції важливіші. Пропустивши акцію конкурента, ви ризикуєте втратити до 30% конверсії. Парсер дає вам інформацію за хвилини, дозволяючи миттєво запустити контракцію. Як показує наш досвід, понад 80% клієнтів починають контракцію протягом години після отримання сповіщення про знижки.

Принцип роботи парсера акцій

Використовуємо PHP 8.3, Laravel 11, Symfony DomCrawler для парсингу та PostgreSQL для зберігання. Розробка парсера на PHP 8.3 забезпечує високу продуктивність. Scraper для ecommerce ідеально підходить для інтернет-магазинів. Ключові компоненти описані нижче.

Код парсера сторінок акцій
// app/Services/PromotionScraper/PromotionPageScraper.php class PromotionPageScraper { public function scrapePromotionsPage(string $url): array { $html = $this->fetch($url); $crawler = new Crawler($html); $promotions = []; // Стандартні блоки акцій $crawler->filter('.promotion-card, .sale-block, .promo-item, [data-promo]') ->each(function (Crawler $node) use (&$promotions) { $promo = $this->extractPromotion($node); if ($promo) $promotions[] = $promo; }); // Якщо структуровані блоки не знайдені — парсимо текстом if (empty($promotions)) { $promotions = $this->extractFromText($crawler->text(), $url); } return $promotions; } private function extractPromotion(Crawler $node): ?array { $title = $node->filter('h2, h3, .promo-title, .sale-title')->first()->text(''); if (empty(trim($title))) return null; $description = $node->filter('p, .promo-desc')->first()->text(''); $link = $node->filter('a')->first()->attr('href') ?? ''; // Витягуємо дати з тексту $dates = $this->extractDates($title . ' ' . $description); // Витягуємо відсоток знижки $discount = $this->extractDiscount($title . ' ' . $description); // Шукаємо промокод в тексті $promoCode = $this->extractPromoCode($title . ' ' . $description); return [ 'title' => trim($title), 'description' => trim($description), 'discount_pct'=> $discount, 'promo_code' => $promoCode, 'starts_at' => $dates['start'] ?? null, 'ends_at' => $dates['end'] ?? null, 'url' => $link, ]; } private function extractDiscount(string $text): ?int { // "знижка 30%", "−30%", "30% OFF", "до 50% знижки" if (preg_match('/[-–]?\s*(\d{1,3})\s*%/u', $text, $m)) { return (int) $m[1]; } return null; } private function extractPromoCode(string $text): ?string { // Промокод зазвичай uppercase, 4-12 символів, іноді в лапках або після слова "промокод" if (preg_match('/промокод[:\s]+([A-Z0-9_-]{3,15})/ui', $text, $m)) { return strtoupper($m[1]); } if (preg_match('/promo(?:code)?[:\s]+([A-Z0-9_-]{3,15})/i', $text, $m)) { return strtoupper($m[1]); } // Слова в лапках схожі на промокод if (preg_match('/[«"]([A-Z0-9_-]{4,12})["»]/u', $text, $m)) { return strtoupper($m[1]); } return null; } private function extractDates(string $text): array { $dates = []; // "з 01.03 по 31.03", "до 31 березня", "01.03.2025 - 15.03.2025" $monthMap = [ 'січня'=>'01','лютого'=>'02','березня'=>'03','квітня'=>'04', 'травня'=>'05','червня'=>'06','липня'=>'07','серпня'=>'08', 'вересня'=>'09','жовтня'=>'10','листопада'=>'11','грудня'=>'12', ]; $pattern = '/(\d{1,2})\s+(' . implode('|', array_keys($monthMap)) . ')/ui'; if (preg_match_all($pattern, $text, $matches, PREG_SET_ORDER)) { foreach ($matches as $i => $match) { $day = sprintf('%02d', $match[1]); $month = $monthMap[mb_strtolower($match[2])]; $year = date('Y'); $date = "{$year}-{$month}-{$day}"; if ($i === 0) $dates['start'] = $date; if ($i === 1) $dates['end'] = $date; } } return $dates; } } 

Детектор знижок на товарах

Порівнює стару та нову ціну, розраховує відсоток знижки та знаходить дату закінчення з countdown.

// app/Services/PromotionScraper/ProductSaleDetector.php class ProductSaleDetector { public function detectSale(string $html): ?SaleInfo { $crawler = new Crawler($html); // Шукаємо одночасно стару та нову ціну $originalPriceNode = $crawler->filter( '.original-price, .old-price, del, [data-original-price], s' )->first(); $salePriceNode = $crawler->filter( '.sale-price, .special-price, .discount-price, [data-sale-price]' )->first(); if (!$originalPriceNode->count() || !$salePriceNode->count()) { return null; } $originalPrice = $this->parsePrice($originalPriceNode->text()); $salePrice = $this->parsePrice($salePriceNode->text()); if ($originalPrice <= 0 || $salePrice <= 0 || $salePrice >= $originalPrice) { return null; } $discountPct = round((1 - $salePrice / $originalPrice) * 100); // Термін дії акції $endDate = null; $countdownNode = $crawler->filter('.countdown, [data-countdown], .sale-ends'); if ($countdownNode->count()) { $endDate = $countdownNode->first()->attr('data-end-date') ?? $this->extractDateFromText($countdownNode->first()->text()); } return new SaleInfo( originalPrice: $originalPrice, salePrice: $salePrice, discountPct: $discountPct, endsAt: $endDate, ); } } 

Зберігання та історія

Всі акції зберігаються в таблицю competitor_promotions з історією змін.

// Міграція Schema::create('competitor_promotions', function (Blueprint $table) { $table->id(); $table->foreignId('competitor_id')->constrained(); $table->string('title'); $table->text('description')->nullable(); $table->integer('discount_pct')->nullable(); $table->string('promo_code')->nullable(); $table->string('source_url'); $table->date('starts_at')->nullable(); $table->date('ends_at')->nullable(); $table->boolean('is_active')->default(true); $table->json('affected_categories')->nullable(); $table->timestamp('first_seen_at'); $table->timestamp('last_seen_at'); $table->timestamps(); $table->index(['competitor_id', 'is_active', 'ends_at']); }); 
// app/Jobs/ScrapeCompetitorPromotions.php class ScrapeCompetitorPromotions implements ShouldQueue { public function handle(PromotionPageScraper $scraper): void { $competitor = Competitor::findOrFail($this->competitorId); $promotionUrls = $competitor->promotion_urls ?? []; $currentPromos = []; foreach ($promotionUrls as $url) { $scraped = $scraper->scrapePromotionsPage($url); $currentPromos = array_merge($currentPromos, $scraped); sleep(rand(2, 4)); } // Деактивуємо акції, яких більше немає CompetitorPromotion::where('competitor_id', $this->competitorId) ->where('is_active', true) ->whereNotIn('source_url', array_column($currentPromos, 'url')) ->update(['is_active' => false]); // Оновлюємо або створюємо акції foreach ($currentPromos as $promo) { CompetitorPromotion::updateOrCreate( [ 'competitor_id' => $this->competitorId, 'source_url' => $promo['url'], ], [ 'title' => $promo['title'], 'description' => $promo['description'], 'discount_pct' => $promo['discount_pct'], 'promo_code' => $promo['promo_code'], 'starts_at' => $promo['starts_at'], 'ends_at' => $promo['ends_at'], 'is_active' => true, 'last_seen_at' => now(), 'first_seen_at' => now(), ] ); } // Сповіщення про нові великі акції $newBigSales = CompetitorPromotion::where('competitor_id', $this->competitorId) ->where('first_seen_at', '>=', now()->subMinutes(10)) ->where('discount_pct', '>=', 20) ->get(); if ($newBigSales->isNotEmpty()) { Notification::route('slack', config('monitoring.slack_url')) ->notify(new BigCompetitorSaleNotification($competitor, $newBigSales)); } } } 

Розклад

// Акції — частіше, особливо в п'ятницю/вихідні $schedule->command('scrape:promotions') ->everyTwoHours()->withoutOverlapping(); // Перед вихідними — підвищена частота $schedule->command('scrape:promotions') ->fridays()->at('09:00'); 

Порівняння методів виявлення акцій

Метод Точність Охоплення Складність реалізації
По CSS-селекторам 95% 70% сайтів Низька
Текстовий аналіз regex 80% 90% сайтів Середня
Headless-браузер 99% 99% сайтів Висока

Як впровадити парсер: покрокова інструкція

  1. Аналіз сайтів конкурентів — виявлення структури сторінок акцій.
  2. Проектування архітектури парсера та схеми даних.
  3. Розробка парсера та детектора знижок.
  4. Тестування на 3–5 сайтах, виправлення багів.
  5. Деплой на сервер, налаштування cron та сповіщень.

Процес роботи

Етап Тривалість Результат
Аналіз сайтів 1 день Виявлення структури сторінок акцій
Проектування 1 день Архітектура парсера, схема даних
Розробка 2-3 дні Код парсера, детектор знижок, сповіщення
Тестування 1 день Перевірка на 3-5 сайтах, виправлення багів
Деплой 0.5 дня Розгортання на сервері, налаштування cron

Типові помилки при парсингу акцій

  • Акція прихована за JavaScript-рендерингом — потрібен headless-браузер.
  • Промокод видається тільки після кліку — знадобиться емуляція дій.
  • Дати вказані у відносному форматі («до кінця тижня») — потрібен кастомний парсер.
  • Зміна структури сайту призводить до поломки — використовуйте fallback-алгоритми.

Що входить в роботу

  • Парсер для 3-5 сайтів конкурентів (під ключ)
  • Дашборд для перегляду історії акцій
  • Сповіщення в Slack (Telegram за запитом)
  • Документація та API для інтеграції
  • Навчання команди (1 година)
  • Місяць підтримки після деплою

Терміни орієнтовно

Розробка базового функціоналу — від 5 до 8 робочих днів. Складні проекти з нестандартною структурою сайтів — до 14 днів. Точну оцінку даємо після аудиту цільових ресурсів. Зв'яжіться з нами — безкоштовно оцінимо проект. Отримайте консультацію та замовте розробку парсера, щоб отримати конкурентну перевагу.

Додаткові можливості

Наш парсер забезпечує парсинг сайтів знижок та сповіщення про знижки. Вартість рішення від $2000, а щомісячна економія сягає $3000 — це в 1.5 рази вигідніше за наймання окремого маркетолога.