Как я создал Telegram-бота для автоматизации Wildberries

· 4 мин чтения

Привет! Расскажу о проекте, который сэкономил сотням селлеров Wildberries часы рутинной работы — Telegram-боте wb_bot_pro для полной автоматизации работы с маркетплейсом.

Проблема

Исходная ситуация:

  • Селлеры тратили 2-3 часа в день на ручную выгрузку данных из личного кабинета WB
  • Отчёты по продажам собирались вручную в Excel
  • Новые заказы FBS пропускались, потому что не было уведомлений
  • Аналитика велась «на глазок», без точных метрик
  • Синхронизация данных ломалась при каждом изменении API

Решение

Разработал полнофункционального Telegram-бота с микросервисной архитектурой:

📦 Основные модули

1. Автоматическая синхронизация данных (auto_data_sync.py)

  • При добавлении магазина загружает историю за 365 дней (продажи, заказы) и 90 дней (отчёты реализации)
  • Непрерывное обновление каждые 30 минут в рабочее время
  • Чанковая загрузка с обходом лимитов API (1 запрос в минуту)
  • Сохранение прогресса в SQLite для восстановления после перезапуска

2. FBS-заказы и поставки (supplies.py)

  • Получение новых сборочных заданий через /api/v3/orders
  • Генерация PDF со стикерами Wildberries + баркодами Code128
  • Поддержка принтеров этикеток 58x40 мм
  • Автоматическая пагинация: 2 элемента на страницу

3. Аналитика и отчёты (analytics/)

  • data_loader.py — загрузка данных из 7 таблиц SQLite
  • status_enricher.py — обогащение статусов (realized, returned, canceled, sold, pending)
  • metrics_calculator.py — расчёт выручки, прибыли, логистики, штрафов, уровня возвратов
  • reports_xlsx.py — Excel с 6 листами (сводка, детализация, ТОП-10, диагностика)
  • reports_images.py — 4 графика (статусы, динамика, ТОП-товаров, сводка)

4. Уведомления (notifications.py)

  • Мгновенные алерты о новых FBS-заказах
  • Фото товара + артикул + размер + цена + баркод
  • Поддержка нескольких пользователей на один магазин
  • Дедупликация через таблицу order_notifications

5. Управление ценами (prices.py)

  • Выгрузка Excel-шаблона с товарами
  • Массовое обновление закупочных цен
  • Валидация структуры файла
  • Привязка к магазину через chat_id

🛠️ Технический стек

  • Язык: Python 3.10+
  • Telegram Bot Framework: aiogram 3.x (асинхронный)
  • HTTP Client: aiohttp + pydantic для валидации
  • База данных: SQLite с потокобезопасными контекстными менеджерами
  • PDF: ReportLab + PIL для генерации этикеток
  • Excel: openpyxl для отчётов и шаблонов
  • Графики: matplotlib с кастомными стилями
  • Логирование: кастомный logger с фильтрацией Unicode

📊 Архитектура базы данных

shops              -- Магазины (api_token, name)
users              -- Пользователи Telegram (chat_id, channel_id)
user_shops         -- Связь пользователей и магазинов
orders             -- FBS сборочные задания
sales              -- Продажи и возвраты (90 дней)
realization_reports -- Отчёты реализации (с 29.01.2024)
prices             -- Закупочные цены и скидки
stocks             -- Остатки по складам
order_notifications -- Уведомлённые заказы
products           -- Карточки товаров
seller_warehouses  -- Склады продавца
seller_stocks      -- Остатки по складам

🔁 Как работает синхронизация

# Историческая загрузка при добавлении магазина
async def start_initial_sync(shop_id: int, api_token: str):
    # 1. Загружаем продажи за 365 дней (чанками по 30 дней)
    await _load_historical_chunk("sales")

    # 2. Загружаем заказы за 365 дней
    await _load_historical_chunk("supplier_orders")

    # 3. Загружаем отчёты реализации за 90 дней (по неделям)
    await _load_historical_chunk("realization_reports")

    # 4. Загружаем FBS заказы за 120 дней
    await _load_historical_chunk("orders")

    # 5. Синхронизируем товары и остатки
    await _sync_products()
    await _sync_warehouses_and_stocks()

# Непрерывное обновление в фоне
async def _continuous_sync_loop():
    while True:
        if _should_sync_now():  # Не синхронизируем 23:00-06:00 МСК
            await _sync_recent_data(days=7)
        await asyncio.sleep(3600)  # Проверка каждый час

🎯 Ключевые фичи

Обработка лимитов API:

  • Statistics API: 1 запрос в минуту → очередь запросов с asyncio.sleep(60)
  • Marketplace API: 300 запросов в минуту, всплеск 20 → троттлинг
  • Пагинация через rrd_id для отчётов реализации
  • Курсорная пагинация для товаров (updated_at + nmID)

Работа с датами:

  • Все даты в часовом поясе Москва (UTC+3)
  • Формат RFC3339 для API: 2024-03-15T23:59:59
  • Unix timestamp для Marketplace API
  • Автоматическое определение периода для отчётов

Целостность данных:

  • DataHealthChecker проверяет дубликаты и актуальность
  • Автоматическое исправление расхождений между таблицами
  • Таблица order_notifications предотвращает дублирование уведомлений
  • Soft delete для устаревших товаров

📈 Результат

Метрики после внедрения:

  • Время на сбор отчётов: 3 часа → 3 минуты
  • Количество пропущенных заказов: 15% → 0%
  • Актуальность данных: 1 раз в неделю → каждые 30 минут
  • Онбординг новых селлеров: 2 дня → 15 минут

Количество магазинов на одном боте: до 50 одновременно Средний объём данных: ~100k строк продаж + 50k заказов на магазин

Выводы

Главный урок: не экономь на обработке ошибок API. Wildberries API может вернуть 500 ошибку в любой момент, особенно при загрузке больших отчётов. Всегда делай retry с экспоненциальной задержкой и логируй каждый запрос.

Второй важный момент: SQLite достаточно для 95% случаев. При правильной индексации и использовании контекстных менеджеров он легко тянет 50 магазинов с миллионами строк данных.

Если делаешь бота для маркетплейса — сразу закладывай поддержку нескольких API (Statistics + Marketplace), потому что данные в них пересекаются, но не дублируют друг друга полностью.


P.S. Исходный код проекта доступен в репозитории. Если ты селлер на Wildberries и хочешь автоматизировать рутину — пиши, помогу настроить!