Разработка бота-парсера новых поступлений начинается с анализа структуры каталога поставщика. Парсинг веб-страниц позволяет автоматизировать сбор данных. Мы выбираем оптимальную стратегию детекции дельты: по дате добавления, по разделу «Новинки» или по сравнению списка 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 месяцев за счет экономии времени менеджеров и сокращения упущенных продаж. Получите консультацию по вашему проекту — мы рассчитаем стоимость и сроки.







