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







