Только качественные заявки с СМС-верификацией от api-master.ru

Антон Миславский
программист

Как загрузить данные из API WB, Ozon в Yandex Cloud и ваш SQL сервер

Приветствую, меня зовут Антон Миславский — я программист и data-аналитик. Я и моя команда помогает селлерам маркетплейсов (Яндекс Маркета, OZON, Wb, Авито) автоматизировать процессы и получать отчёты из API в Google и Яндекс-таблицы, БД Yandex Cloud, PostgreSQL, Clickhouse.

На этих данных менеджеры и разработчики таблиц создают дашборды, РНП, P&L отчёты, считаю юнит-экономику

Как селлеру настроить выгрузку данных из API Wildberries в Yandex Cloud: Пошаговое руководство

Проблема: Многие селлеры строят аналитику на базе Google Таблиц. При росте объемов данных этот инструмент быстро "умирает": всплывают жесткие лимиты по количеству строк и ячеек, документы виснут. Дополнительная головная боль — нестабильная работа сервисов Google из-за ограничений сети в РФ.
Решение: Миграция инфраструктуры с Google Таблиц в надежное облако.
В этой статье мы даем готовую инструкцию, как перенести выгрузку данных из API Wildberries в Yandex Cloud на базу Managed Service for ClickHouse. Рассмотрим экономичный, но производительный вариант архитектуры, которого с запасом хватит для задач селлера.

Архитектура: Бюджетный кластер для старта

Чтобы не переплачивать за инфраструктуру, используем конфигурацию с одним хостом. Этого более чем достаточно для хранения и быстрой обработки миллионов строк из API WB.
Создать кластер можно через веб-консоль Yandex Cloud или одной командой через консольную утилиту YC CLI.

Какую базу данных выбрать?

Выбор СУБД зависит от ваших бизнес-задач:
  1. PostgreSQL (Managed Service for PostgreSQL): Универсальный "швейцарский нож". Идеально, если у вас сложная бизнес-логика, много связей между таблицами (например, товары, склады, себестоимость) и вы планируете обновлять отдельные записи (UPDATE).
  2. ClickHouse (Managed Service for ClickHouse): Оптимальный выбор для чистой аналитики (OLAP). Если ваша цель — загрузить миллионы строк продаж и мгновенно строить по ним графики в дашбордах (например, в DataLens), ClickHouse справится лучше всех.
  3. YDB (Yandex Database): Распределенная транзакционная база данных (OLTP), доступная в Serverless-режиме. Отличный выбор, если вы пишете микросервисы (например, Telegram-ботов для менеджеров) с рваной нагрузкой. Вы платите только за фактические запросы.

Подготовка окружения: Где запускать код и как установить библиотеки

Где запускать код? На этапе тестирования и первичной настройки удобнее всего запускать скрипты на вашем локальном компьютере (например, в IDE VS Code, Cursor, Antigravity). Когда код будет отлажен, его можно перенести на виртуальную машину или поставить на удаленный сервер и настроить в планировщик CRON для ежедневного запуска, либо обернуть в Yandex Cloud Functions.

Установка библиотек (Инструкция для macOS):

Для работы с API и базами данных нам потребуются сторонние библиотеки. Откройте приложение «Терминал» (Terminal) на вашем Mac и выполните следующие шаги:
Убедитесь, что у вас установлен Python 3. Создайте виртуальное окружение, чтобы не засорять систем
Для всех примеров ниже мы используем один и тот же JSON-ответ от API продаж Wildberries:
python3 -m venv wb_analytics_env 
source wb_analytics_env/bin/activate 
pip install requests 
pip install yandexcloud requests clickhouse-connect 

Установите драйвер (SDK) для той базы данных, которую вы выбрали:

  • Для PostgreSQL: pip install psycopg2-binary (используем версию binary, чтобы избежать проблем с компиляцией).
  • Для ClickHouse: pip install clickhouse-connect
  • Для YDB: pip install ydb
  • Примечание для пользователей Windows и Linux: Сам Python-код из нашей статьи будет работать у вас абсолютно так же — он кроссплатформенный. Однако команды для активации виртуального окружения (например, wb_analytics_env\Scripts\activate для Windows) и процесс установки некоторых системных зависимостей (особенно для PostgreSQL) могут незначительно отличаться.
Пример команды Yandex Cloud CLI для создания кластера с публичным доступом:
Где b3-c1-m4 — это минимальный тариф (burstable), 10 ГБ диска, создание БД wb_data и пользователя ch_admin.
Важно: Если создаете кластер через веб-интерфейс, выберите 1 хост, отключите ZooKeeper (он не нужен без репликации), и обязательно включите публичный доступ, чтобы скрипты и BI-системы могли подключаться извне.
yc managed-clickhouse cluster create \
  --name wb-analytics \
  --network-name default \
  --host type=clickhouse,zone-id=ru-central1-a,assign-public-ip=true \
  --clickhouse-resource-preset b3-c1-m4 \
  --clickhouse-disk-size 10 \
  --database name=wb_data \
  --user name=ch_admin,password=SecurePass123!

api-master.ru — услуга выгрузке данных для селлеров маркетплейсов

  • Выгружаем данные из любых API в любые БД
  • Настраиваем внутреннюю рекламу на маркетплейсах
  • Внедряем ИИ в ваш бизнес

Как получить данные кластера для подключения в Yandex Cloud

После того как кластер перейдет в статус Alive, вам нужно хост сервера (его адрес) для вставки в скрипт.
  1. Зайдите в консоль Yandex Cloud и перейдите в сервис Managed Service for ClickHouse.
  2. Кликните на ваш кластер (wb-analytics).
  3. Перейдите в раздел Хосты в левом меню.
  4. В столбце "Имя хоста" вы увидите длинный адрес, который заканчивается на .mdb.yandexcloud.net (например, rc1a-xxxxxx.mdb.yandexcloud.net). Это и есть ваш FQDN (Fully Qualified Domain Name), который нужно использовать в коде.
  • Также в разделе "Группы безопасности" вашего кластера убедитесь, что разрешен входящий TCP-трафик на порт 8443.

Безопасность: Ключи и сертификаты

  1. API-ключи Wildberries: Создаются в личном кабинете продавца WB ("Доступ к API").
  2. SSL-сертификат (CA Certificate): Обязательно скачайте сертификат Яндекса (ищите в справке Yandex Cloud статью "Подключение к кластеру ClickHouse"). Без файла YandexInternalRootCA.crt скрипт отклонит соединение.


Python скрипт для выгрузки отчета продаж WB в базу данных

Для примера возьмем метод для выгрузку продаж (Sales) из API WB.
Вот так выглядит типичный ответ API WB в формате JSON:
Для всех примеров ниже мы используем один и тот же JSON-ответ от API продаж Wildberries:
[
  {
    "date": "2026-03-04T18:08:31",
    "lastChangeDate": "2026-03-06T10:11:07",
    "warehouseName": "Москва",
    "warehouseType": "Склад продавца",
    "countryName": "Россия",
    "oblastOkrugName": "Центральный федеральный округ",
    "regionName": "Московский",
    "supplierArticle": "12345",
    "nmId": 98755111,
    "barcode": "123453119222",
    "category": "Цифровые товары",
    "subject": "Подписка",
    "brand": "api-master.ru",
    "techSize": "0",
    "incomeID": 16735451,
    "isSupply": false,
    "isRealization": true,
    "totalPrice": 15000,
    "discountPercent": 18,
    "spp": 26,
    "finishedPrice": 1145,
    "priceWithDisc": 1547,
    "isCancel": true,
    "cancelDate": "2026-03-09T00:00:00",
    "sticker": "923912515",
    "gNumber": "11113162218572569531",
    "srid": "11.rf921fce16823117b0nhj96222382382.3.0"
  }
]
Вариант 1: Создаем таблицу в БД Yandex Cloud на PostgreSQL
DDL-запрос для создания таблицы продаж Wildberries
CREATE TABLE IF NOT EXISTS wb_sales (
    date DateTime,
    lastChangeDate DateTime,
    warehouseName String,
    warehouseType String,
    countryName String,
    oblastOkrugName String,
    regionName String,
    supplierArticle String,
    nmId UInt64,
    barcode String,
    category String,
    subject String,
    brand String,
    techSize String,
    incomeID UInt64,
    isSupply UInt8,       -- ClickHouse хранит boolean как 0 или 1
    isRealization UInt8,
    totalPrice Float64,
    discountPercent UInt8,
    spp UInt8,
    finishedPrice Float64,
    priceWithDisc Float64,
    isCancel UInt8,
    cancelDate DateTime,
    sticker String,
    gNumber String,
    srid String
) ENGINE = MergeTree()
ORDER BY (date, nmId);
Python-скрипт для загрузки данных в БД
import requests
import psycopg2
from psycopg2.extras import execute_values

# Подключение к PostgreSQL в Yandex Cloud
conn = psycopg2.connect(
    host="rc1a-xxxxxx.mdb.yandexcloud.net",
    port=6432,
    dbname="wb_data",
    user="pg_user",
    password="SecurePass123!",
    target_session_attrs="read-write"
)
cursor = conn.cursor()

# Запрос к WB
url = "https://statistics-api.wildberries.ru/api/v1/supplier/sales?dateFrom=2026-03-01"
headers = {"Authorization": "ВАШ_ТОКЕН"}
wb_data = requests.get(url, headers=headers).json()

if wb_data:
    columns = list(wb_data[0].keys())
    # Формируем кортежи для быстрой вставки
    values = [[row.get(col) for col in columns] for row in wb_data]
    
    insert_query = f"""
        INSERT INTO wb_sales ({','.join(columns)}) 
        VALUES %s 
        ON CONFLICT (srid) DO NOTHING;
    """
    
    execute_values(cursor, insert_query, values)
    conn.commit()
    print(f"PostgreSQL: загружено {len(values)} строк.")

cursor.close()
conn.close()
Вариант 2: Если выбрали в качестве БД ClickHouse
DDL-запрос:
CREATE TABLE IF NOT EXISTS wb_sales (
    date DateTime,
    lastChangeDate DateTime,
    warehouseName String,
    warehouseType String,
    countryName String,
    oblastOkrugName String,
    regionName String,
    supplierArticle String,
    nmId UInt64,
    barcode String,
    category String,
    subject String,
    brand String,
    techSize String,
    incomeID UInt64,
    isSupply UInt8,       -- ClickHouse хранит boolean как 0 или 1
    isRealization UInt8,
    totalPrice Float64,
    discountPercent UInt8,
    spp UInt8,
    finishedPrice Float64,
    priceWithDisc Float64,
    isCancel UInt8,
    cancelDate DateTime,
    sticker String,
    gNumber String,
    srid String
) ENGINE = MergeTree()
ORDER BY (date, nmId);
Python-скрипт (используем clickhouse-connect):
import requests
import clickhouse_connect

# Подключение к ClickHouse
client = clickhouse_connect.get_client(
    host='rc1a-xxxxxx.mdb.yandexcloud.net',
    port=8443,
    username='ch_user',
    password='SecurePass123!',
    secure=True,
    ca_cert='/path/to/YandexInternalRootCA.crt'
)

# Запрос к WB
url = "https://statistics-api.wildberries.ru/api/v1/supplier/sales?dateFrom=2026-03-01"
headers = {"Authorization": "ВАШ_ТОКЕН"}
wb_data = requests.get(url, headers=headers).json()

if wb_data:
    columns = list(wb_data[0].keys())
    data_to_insert = []
    
    for row in wb_data:
        # ClickHouse не принимает пустые даты "0001-01-01"
        if row.get('cancelDate') == "0001-01-01T00:00:00":
            row['cancelDate'] = "1970-01-01T00:00:00" 
        data_to_insert.append([row.get(col) for col in columns])

    # Массовая вставка
    client.insert('wb_sales', data_to_insert, column_names=columns)
    print(f"ClickHouse: загружено {len(data_to_insert)} строк.")
Вариант 3: Serverless Yandex DB - до 1.000.000 строк бесплатно!
В YDB используется строгая типизация и обязательные первичные ключи (Primary Key).
Язык запросов — YQL,
DDL-запрос (выполняется в консоли Yandex Cloud):
CREATE TABLE wb_sales (
    date Datetime,
    lastChangeDate Datetime,
    warehouseName Utf8,
    warehouseType Utf8,
    countryName Utf8,
    oblastOkrugName Utf8,
    regionName Utf8,
    supplierArticle Utf8,
    nmId Uint64,
    barcode Utf8,
    category Utf8,
    subject Utf8,
    brand Utf8,
    techSize Utf8,
    incomeID Uint64,
    isSupply Bool,
    isRealization Bool,
    totalPrice Double,
    discountPercent Uint32,
    spp Uint32,
    finishedPrice Double,
    priceWithDisc Double,
    isCancel Bool,
    cancelDate Datetime,
    sticker Utf8,
    gNumber Utf8,
    srid Utf8,
    PRIMARY KEY (srid) -- YDB требует явный первичный ключ
);
Python-скрипт для YDB (используем официальный SDK ydb):
Для YDB оптимально использовать метод bulk_upsert, который загружает данные массивом и автоматически обновляет существующие записи по первичному ключу.
import requests
import ydb
import ydb.iam
from datetime import datetime

# Настройки YDB
endpoint = "grpcs://ydb.serverless.yandexcloud.net:2135"
database = "/ru-central1/b1g.../etn..." # Ваш путь к БД из консоли

# Авторизация (через сервисный аккаунт или IAM-токен)
driver_config = ydb.DriverConfig(
    endpoint, database, credentials=ydb.iam.MetadataUrlCredentials()
)

# Запрос к WB
url = "https://statistics-api.wildberries.ru/api/v1/supplier/sales?dateFrom=2026-03-01"
headers = {"Authorization": "ВАШ_ТОКЕН"}
wb_data = requests.get(url, headers=headers).json()

if wb_data:
    # Конвертируем строки дат в timestamp для YDB
    for row in wb_data:
        try:
            row['date'] = int(datetime.strptime(row['date'], "%Y-%m-%dT%H:%M:%S").timestamp())
            if row.get('cancelDate') and row['cancelDate'] != "0001-01-01T00:00:00":
                row['cancelDate'] = int(datetime.strptime(row['cancelDate'], "%Y-%m-%dT%H:%M:%S").timestamp())
            else:
                row['cancelDate'] = None
        except ValueError:
            pass

    # YDB bulk_upsert принимает список словарей с типами
    with ydb.Driver(driver_config) as driver:
        driver.wait(timeout=5)
        # Описываем типы столбцов для Bulk Upsert
        column_types = ydb.BulkUpsertColumns()
        column_types.add_column('srid', ydb.OptionalType(ydb.PrimitiveType.Utf8))
        column_types.add_column('date', ydb.OptionalType(ydb.PrimitiveType.Datetime))
        column_types.add_column('nmId', ydb.OptionalType(ydb.PrimitiveType.Uint64))
        # ... (добавьте остальные типы согласно DDL) ...
        
        # Выполняем массовую вставку
        driver.table_client.bulk_upsert(f"{database}/wb_sales", wb_data, column_types)
        print(f"YDB: загружено {len(wb_data)} строк.")
Резюме: Любой из этих скриптов можно обернуть в Docker-контейнер, закинуть в Yandex Serverless Containers или запускать по Cron на обычной виртуальной машине.
Кстати, если у вас нет времени разбираться с архитектурой, серверами и кодом самостоятельно, наша команда настраивает выгрузку данных по API в любые базы данных (от классического Postgres до YDB) под ключ. А чтобы собранная аналитика радовала растущими графиками, мы также занимаемся профессиональной настройкой рекламы. Пишите, обсудим вашу задачу.