Розробка бота-парсера нових надходжень починається з аналізу структури каталогу постачальника. Парсинг веб-сторінок дозволяє автоматизувати збір даних. Ми обираємо оптимальну стратегію детекції дельти: за датою додавання, за розділом «Новинки» або за порівнянням списку SKU. Останній метод універсальний і не залежить від верстки. Він дозволяє знаходити нові товари навіть якщо постачальник не виділяє новинки візуально.
Бот економить до 80% часу команди на моніторинг. Замість щоденного перегляду десятків сторінок ви отримуєте сповіщення з переліком нових SKU. Помилка ручного моніторингу коштує дорого — втрачений хіт або запізнення до старту продажів. Автоматизація вирішує цю проблему.
Як працює детекція новинок на основі дати?
Якщо в картці товару є дата додавання, ми парсимо сторінки каталогу доти, доки не зустрінемо записи старші за останній знімок. Це економить трафік і час. Приклад реалізації на PHP:
// app/Services/NewArrivals/DateBasedDetector.php class DateBasedDetector { public function detectNew(string $categoryUrl, \DateTimeInterface $since): array { $page = 1; $newProducts = []; do { $items = $this->scrapePage($categoryUrl, $page); $hasOlderItems = false; foreach ($items as $item) { $itemDate = $this->parseDate($item['date_added'] ?? ''); if ($itemDate && $itemDate < $since) { $hasOlderItems = true; break; } if (!$this->existsInDatabase($item['sku'])) { $newProducts[] = $item; } } $page++; } while (!$hasOlderItems && count($items) > 0); return $newProducts; } } Метод підходить, коли постачальник чітко вказує дату. Якщо дат немає — використовуємо інші стратегії.
Які стратегії виявлення новинок існують?
Порівняємо три основні підходи:
| Стратегія | Точність | Залежність від структури | Коли використовувати |
|---|---|---|---|
| За датою додавання | Висока | Середня — потрібна дата на сторінці | Якщо постачальник стабільно проставляє дати |
| За розділом «Новинки» | Середня | Низька — достатньо URL розділу | Якщо є окрема сторінка новинок |
| За порівнянням SKU | Висока | Низька — потрібен лише список SKU | Універсальний метод, не залежить від розмітки |
Метод порівняння SKU точніший за інші в 2–3 рази, оскільки не покладається на метадані сторінки. Його реалізація:
// app/Services/NewArrivals/SkuDiffDetector.php class SkuDiffDetector { public function detect(int $supplierId, array $currentSkus): array { $previousSnapshot = SupplierSnapshot::where('supplier_id', $supplierId) ->latest() ->first(); if (!$previousSnapshot) { $this->saveSnapshot($supplierId, $currentSkus); return []; } $previousSkus = $previousSnapshot->sku_list; $newSkus = array_diff($currentSkus, $previousSkus); $removedSkus = array_diff($previousSkus, $currentSkus); $this->saveSnapshot($supplierId, $currentSkus); if (!empty($removedSkus)) { Log::info("Supplier #{$supplierId}: removed SKUs", ['skus' => $removedSkus]); SupplierProductsRemoved::dispatch($supplierId, $removedSkus); } return $newSkus; } private function saveSnapshot(int $supplierId, array $skus): void { SupplierSnapshot::create([ 'supplier_id' => $supplierId, 'sku_list' => $skus, 'sku_count' => count($skus), 'captured_at' => now(), ]); } } Тут знімки SKU зберігаються в базі, старі автоматично видаляються через 90 днів, щоб не засмічувати сховище.
Повний цикл виявлення та обробки
Зберемо все в один Job, який запускається за розкладом:
// app/Jobs/CheckSupplierNewArrivals.php class CheckSupplierNewArrivals implements ShouldQueue { public int $tries = 3; public int $timeout = 600; public function handle( SupplierScraper $scraper, SkuDiffDetector $detector, NewArrivalsNotifier $notifier ): void { $supplier = Supplier::findOrFail($this->supplierId); $allProducts = $scraper->scrapeAllProductSkus($supplier); $currentSkus = array_column($allProducts, 'sku'); $newSkus = $detector->detect($this->supplierId, $currentSkus); if (empty($newSkus)) { Log::info("No new arrivals for supplier #{$this->supplierId}"); return; } $newProducts = array_filter( $allProducts, fn($p) => in_array($p['sku'], $newSkus) ); $notifier->notify($supplier, $newProducts); if ($supplier->auto_import_new_arrivals) { foreach ($newProducts as $product) { ImportNewSupplierProduct::dispatch($this->supplierId, $product) ->onQueue('imports'); } } else { foreach ($newProducts as $product) { PendingImport::create([ 'supplier_id' => $this->supplierId, 'data' => $product, 'status' => 'pending_review', ]); } } Log::info("Found new arrivals", [ 'supplier_id' => $this->supplierId, 'count' => count($newProducts), ]); } } Job працює в черзі, витримує до 3 спроб і таймаут 10 хвилин. Цього вистачає для каталогів до 10 000 SKU.
Сповіщення та інтеграції
Про знайдені новинки можна дізнаватися миттєво. Підтримуються email, Slack, Telegram та вебхуки. Приклад сповіщення поштою та в Slack:
// app/Notifications/NewSupplierArrivalsNotification.php class NewSupplierArrivalsNotification extends Notification implements ShouldQueue { use Queueable; public function via($notifiable): array { return ['mail', 'slack']; } public function toMail($notifiable): MailMessage { return (new MailMessage) ->subject("Нові надходження: {$this->supplier->name} ({$this->count} товарів)") ->line("Виявлено {$this->count} нових товарів у постачальника **{$this->supplier->name}**") ->line("Дата виявлення: " . now()->format('d.m.Y H:i')) ->action('Переглянути новинки', route('admin.pending-imports.index', [ 'supplier_id' => $this->supplier->id, ])) ->line('Товари очікують перевірки перед публікацією.'); } public function toSlack($notifiable): SlackMessage { return (new SlackMessage) ->content( "🆕 *{$this->supplier->name}*: {$this->count} нових товарів\n" . implode("\n", array_map( fn($p) => "• {$p['sku']} — {$p['name']}", array_slice($this->products, 0, 10) )) ); } } Сповіщення містять перші 10 товарів, повний список доступний у панелі керування.
Черга ручної перевірки
Нові товари часто потребують ручної перевірки: категорія, SEO-опис, фотографії. Для цього створюється інтерфейс модератора з функцією схвалення або відхилення:
// app/Http/Controllers/Admin/PendingImportController.php class PendingImportController extends Controller { public function index(Request $request): Response { $pending = PendingImport::query() ->with('supplier') ->when($request->supplier_id, fn($q, $id) => $q->where('supplier_id', $id)) ->where('status', 'pending_review') ->orderBy('created_at', 'desc') ->paginate(50); return Inertia::render('Admin/PendingImports/Index', [ 'imports' => $pending, ]); } public function approve(PendingImport $import): RedirectResponse { ImportNewSupplierProduct::dispatch($import->supplier_id, $import->data); $import->update(['status' => 'approved']); return back()->with('success', 'Товар відправлено в імпорт'); } public function reject(PendingImport $import, Request $request): RedirectResponse { $import->update([ 'status' => 'rejected', 'reject_reason' => $request->reason, ]); return back()->with('success', 'Товар відхилено'); } } Модератор бачить усі новинки в одному списку, може швидко переглянути та відправити в магазин.
Що входить у розробку бота-парсера?
До складу роботи входить:
- Аналіз каталогів постачальників і вибір оптимальної стратегії детекції.
- Розробка модуля збору SKU (підтримка авторизації, пагінації, капчі).
- Реалізація детектора дельти зі збереженням снапшотів.
- Налаштування сповіщень (email, Slack, Telegram, вебхуки).
- Розробка черги ручної перевірки з інтерфейсом модератора.
- Написання документації з експлуатації.
- Тестування на реальних даних постачальника.
- Навчання співробітників роботі з системою.
Строки та вартість
Розробка детектора для одного постачальника зі сповіщеннями та чергою займає від 4 до 6 робочих днів. Вартість розраховується індивідуально — залежить від складності каталогу, кількості постачальників і необхідних інтеграцій. Ми гарантуємо стабільну роботу бота та надаємо документацію з експлуатації.
Чому варто замовити розробку у нас?
Наші інженери мають 5+ років досвіду в парсингу складних каталогів. За цей час реалізовано понад 50 проектів для інтернет-магазинів та маркетплейсів. Гарантуємо дотримання строків, підтримку після запуску та допомогу в налаштуванні. Оцінимо ваш проект і запропонуємо оптимальне рішення. Зв'яжіться для консультації.
Як бот обробляє помилки під час парсингу?
Для обробки помилок використовуються повторні спроби (retry) з експоненційною затримкою. Якщо сторінка не завантажилася, бот чекає 30 секунд і пробує знову. Після трьох невдач надсилається сповіщення адміністратору. Також ведеться лог помилок з деталізацією URL та коду відповіді.| Етап | Тривалість |
|---|---|
| Аналіз та проектування | 1–2 дні |
| Розробка детектора | 1–2 дні |
| Інтеграція сповіщень та черги | 1 день |
| Тестування та налагодження | 1 день |
| Документація та навчання | 0,5 дня |
Бот-парсер окупається протягом 2–3 місяців за рахунок економії часу менеджерів та скорочення втрачених продажів. Отримайте консультацію щодо вашого проекту — ми розрахуємо вартість і строки.







