Всем привет!

Ранее я уже писал про парсинг Wildberries, но та статья была довольно узконаправленной и не затрагивала более широкие возможности анализа. Да и с тех пор многое изменилось — тема стала ещё актуальнее, а у читателей накопилось больше вопросов.

Поэтому в этой статье мы разберём тему заново, но уже с акцентом на практическую пользу. Мы разберём:

  • как достать данные о товарах и ценах из WB,

  • как превратить их в удобные таблицы или графики,

  • и как использовать их для анализа конкурентов и рынка в целом.

Всё это будет реализовано на Python.

Все примеры приведены исключительно в образовательных целях. Для коммерческой работы у Wildberries есть официальный Public API.

Сам парсер мы развернем тремя командами в IDE, используя Git, в облачном сервисе Amvera - о нём расскажем чуть ниже.

Где искать данные для парсинга?

Первый вопрос, который возникает у любого, кто хочет парсить Wildberries: а где вообще лежат данные?

Ответ прост: прямо в браузере. Когда мы открываем карточку товара или каталог, сайт делает фоновые запросы к API и принимает информацию в формате JSON.

Посмотреть их можно в DevTools (панель разработчика в браузере):

  1. Откройте любую страницу на Wildberries.

  2. Нажмите F12 - вкладка Network - фильтр Fetch/XHR.

  3. Обновите страницу (CTRL+F5).

  4. В списке запросов вы увидите адреса вида:

Если кликнуть по такому запросу и открыть вкладку Response, то там будет чистый JSON: название, цена, рейтинг, количество отзывов, бренд и другая полезная информация, которую мы будем парсить.

Пример ответа для одного товара:

"products":[
      {
         "__msort":113473,
         "mrel":9862,
         "mksort":65,
         "id":124063338,
         "time1":3,
         "time2":60,
         "wh":117986,
         "dtype":6597069766664,
         "dist":991,
         "root":110497359,
         "kindId":0,
         "brand":"НА ПРИМЕР",
         "brandId":313700,
         "siteBrandId":0,
         "colors":[
            
         ],
         "subjectId":4961,
         "subjectParentId":786,
         "name":"Комиксы детские для мальчиков 5-11 лет",
         "entity":"книги-комиксы",
         "matchId":131554853,
         "supplier":"ОП!",
         "supplierId":222339,
         "supplierRating":4.7,
         "supplierFlags":12224,
         "pics":18,
         "rating":5,
         "reviewRating":4.7,
         "nmReviewRating":4.7,
         "feedbacks":45,
         "nmFeedbacks":45,
         "panelPromoId":1009972,
         "volume":3,
         "viewFlags":1581072,
         "sizes":[
            {
               "name":"",
               "origName":"0",
               "rank":0,
               "optionId":218050475,
               "wh":117986,
               "time1":3,
               "time2":60,
               "dtype":6597069766664,
               "price":{
                  "basic":160000,
                  "product":33700,
                  "logistics":300,
                  "return":0
               },
               "saleConditions":146800640,
               "payload":"длинная-строка"
            }
         ],
         "totalQuantity":1,
         "meta":{
            "tokens":[
               
            ]
         }
      },
      ...
Панель разработчика с информацией об API
Панель разработчика с информацией об API

Где будем запускать парсер?

Прежде чем приступать к работе с данными, давайте разберём, где мы будем развертывать наш парсер.

Запуск произведем в Amvera — облачном сервисе, который позволяет быстро и просто запускать IT-приложения. Проект можно развернуть буквально за 5–10 минут.

Почему Amvera удобен для нас:

  • Бонус при регистрации - 111 рублей. Эти деньги можно получить и использовать для тестирования, отладки или кратковременного запуска приложения без дополнительных условий.

  • Бесплатное проксирование к OpenAI, Gemini, Grok AI и другим сервисам с региональными ограничениями - удобно для интеграций с LLM.

  • Поддержка LLaMA и ChatGPT-инференса. Это значит, что мы можем обрабатывать данные без покупки токенов через зарубежные карты, например для OpenAI.

  • Простое развёртывание приложения: достаточно настроить несколько параметров конфигурации и выполнить 4 команды в терминале через git push. При желании файлы можно загружать и через веб-интерфейс, без командной строки.

Итак, перейдём к практике.

Шаг 0: Как устроен URL поиска Wildberries и что означают его параметры

Когда мы работаем с данными Wildberries через внутреннее API, мы обращаемся к URL вроде этого:

url = f"https://search.wb.ru/exactmatch/ru/common/v18/search?appType=1&curr=rub&dest=-1257786&lang=ru&page=1&query={query}&resultset=catalog&sort=popular&spp=30"

На первый взгляд, это длинная и сложная строка, но на самом деле она состоит из обычных параметров, каждый из которых отвечает за конкретную часть поиска.

Основные параметры

  • appType — тип приложения: 1 = веб, 4 = мобильное. Влияет на формат данных.

  • curr — валюта: rub - рубли, usd - доллары и т.д.

  • dest — регион или склад. Определяет наличие товара и цену.

  • lang — язык интерфейса и описаний товаров.

  • page — номер страницы поиска. Позволяет листать результаты.

  • query — поисковый запрос, например "смартфон" или "наушники".

  • resultset — скорее всего тип поиска. Обычно catalog.

  • sort — сортировка результатов: популярные, по цене, рейтингу и т.д.

  • spp — количество товаров на одной странице.

Шаг 1. Минимальный парсер Wildberries

Для запуска нужен Python >=3.11 и библиотеки requests и pandas

import requests
import pandas as pd

# Создаем строку (пока query = захардкоженое значение)
query = "смартфон"
url = f"https://search.wb.ru/exactmatch/ru/common/v18/search?appType=1&curr=rub&dest=-1257786&lang=ru&page=1&query={query}&resultset=catalog&sort=popular&spp=30"

response = requests.get(url)
data = response.json()

# Получаем список продуктов
products = data.get("products", [])

# Преобразуем данные в удобный для создания DataFrame вид
items = []
for p in products:
    item = {
        "id": p.get("id"),
        "name": p.get("name"),
        "brand": p.get("brand"),
        "price": p.get("sizes", [{}])[0].get("price", {}).get("product", 0) / 100,  # цена в рублях
        "rating": p.get("rating", 0),
        "feedbacks": p.get("feedbacks", 0)
    }
    items.append(item)

df = pd.DataFrame(items)
print(df.head())

# Сохраняем в CSV
df.to_csv("test.csv", index=False)

Что делает этот код:

  1. Достает данные с Wildberries по запросу query.

  2. Берёт нужные поля: id,name,brand,price,rating,feedbacks.

  3. Преобразует в таблицу pandas DataFrame.

  4. Сохраняет в CSV, чтобы можно было удобно анализировать и строить графики.

После выполнения кода выше получаем test.csv с содержимым:

id,name,brand,price,rating,feedbacks
507623823,Смартфон Redmi 13C 8ГБ 256 ГБ 90гц Аndroid синий,Xiaomi,6121.0,5,4
518695516,Смартфон Y19 8 256 ГБ Черный,VIVO,4320.0,0,0
309442000,Смартфон Frbby F10 4 128GB 5000mAh черный,,5301.0,5,53
488478649,Смартфон realne 13C 6 128ГБ,,4517.0,4,15
256099131,"M-HORSE, Смартфон P70 64 ГБ 5000 мАч Светло-серый",MI,4143.0,4,84
365784152,"Смартфон Y04 4+128 Гб, малахитовый черный",vivo,8567.0,5,95
440536590,SPARK Go 1 4+128GB,TECNO,6754.0,5,107
478600034,Galaxy A16 4+128GB,Samsung,10995.0,5,23
384497995,Смартфон A55 Plus 12+512+Разблокировка по лицу и отпечатку,,5569.0,4,68
342395239,SPARK Go 1 3+64GB,TECNO,4945.0,5,150
507519429,Смартфон Y71 6 128 Gb Черный,VIVO,2760.0,5,2
480685679,Смартфон SPARK 40C 128+8GB Ink Black,TECNO,9272.0,5,39
...

Шаг 2. Визуализация данных

После того как мы собрали данные о товарах и ценах из Wildberries и сохранили их в CSV (test.csv), следующим шагом будет анализ и визуализация. Это позволит быстро понять, какие бренды популярны, как распределены цены, и где есть возможности для конкуренции.

Мы будем использовать Python, а именно библиотеки:

  • pandas — для работы с таблицами,

  • matplotlib и seaborn — для графиков.

2.1. Гистограмма цен

Сначала посмотрим, как распределены цены на смартфоны:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv("test.csv")

plt.figure(figsize=(10,6))
sns.histplot(df['price'], bins=20, kde=True)
plt.title("Распределение цен на смартфоны")
plt.xlabel("Цена, руб")
plt.ylabel("Количество товаров")
plt.tight_layout()
plt.savefig("price.png")
plt.close()

Вывод сохраняется в price.png:

Гистограмма распределения цен, полученных в нашем парсере Wildberries
Гистограмма распределения цен, полученных в нашем парсере Wildberries

2.2. Топ брендов по количеству товаров

Теперь посмотрим, какие бренды представлены больше всего:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv("test.csv")

top_brands = df['brand'].value_counts().head(10)
plt.figure(figsize=(10,6))
sns.barplot(x=top_brands.index, y=top_brands.values)
plt.title("Топ-10 брендов по количеству товаров")
plt.xlabel("Бренд")
plt.ylabel("Количество товаров")
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig("brands_count.png")
plt.close()

Вид brands_count.png:

Гистограмма распределения брендов, полученных в нашем парсере Wildberries
Гистограмма распределения брендов, полученных в нашем парсере Wildberries

2.3. Топ брендов по средней цене

Интересно также посмотреть, у каких брендов самые дорогие товары:

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv("test.csv")

brand_price = df.groupby('brand')['price'].mean().sort_values(ascending=False).head(10)
plt.figure(figsize=(10,6))
sns.barplot(x=brand_price.index, y=brand_price.values)
plt.title("Топ-10 брендов по средней цене")
plt.xlabel("Бренд")
plt.ylabel("Средняя цена, руб")
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig("brands_avg_price.png")
plt.close()

График brands_avg_price.png:

Гистограмма распределения брендов по цене
Гистограмма распределения брендов по цене

Шаг 3. Создаём Телеграм-бота для анализа Wildberries

Теперь мы можем сделать бота, которому достаточно написать команду /search <запрос>;, а бот:

  1. Получает товары с WB по вашему запросу,

  2. Строит графики и сохраняет их в PNG,

  3. Отправляет графики пользователю.

3.1. Установка зависимостей

В проекте будут использованы следующие зависимости:

  • aiogram — для бота Telegram

  • pandas — работа с таблицами

  • matplotlib и seaborn — графики

  • requests — запросы к API WB

  • python-dotenv — хранение токена бота в .env (нужно только локально, в Amvera будем использовать интерфейс)

Если будете тестировать локально — создайте .env с содержимым:

TOKEN=ВАШ_ТОКЕН_ТЕЛЕГРАМ

Напишем файл requirements.txt, содержащий список наших зависимостей. Это поможет нам в дальнейшем развертывании решения.

requirements.txt:

aiogram==3.22.0
requests==2.32.5
pandas==2.3.2
matplotlib==3.10.6
seaborn==0.13.2
python-dotenv==1.1.1

3.2. Код бота

import asyncio
import requests
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import io
import logging
import os

from dotenv import load_dotenv

from aiogram import Bot, Dispatcher, types, F
from aiogram.types import InlineKeyboardButton, CallbackQuery, InputFile
from aiogram.filters import CommandStart, Command, CommandObject
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.client.default import DefaultBotProperties
from aiogram.enums.parse_mode import ParseMode

logging.basicConfig(level=logging.INFO)
load_dotenv()

bot = Bot(os.getenv("TOKEN"), default=DefaultBotProperties(parse_mode=ParseMode.HTML)) # Создайте переменную окружения TOKEN с токеном вашего бота  
dp = Dispatcher()

@dp.message(Command("search"))
async def search_wb(message: types.Message):
    query = message.text.split(" ", 1)[1]
    if not query:
        await message.answer("Пожалуйста, укажи, что искать: /search &lt;запрос&gt;")
        return

    await message.answer(f"Ищу товары по запросу: {query}...")

    # Получаем и парсим данные
    url = f"https://search.wb.ru/exactmatch/ru/common/v18/search?appType=1&amp;curr=rub&amp;dest=-1257786&amp;lang=ru&amp;page=1&amp;query={query}&amp;resultset=catalog&amp;sort=popular&amp;spp=30"
    response = requests.get(url)
    data = response.json()
    products = data.get("products", [])

    items = []
    for p in products:
        item = {
            "id": p.get("id"),
            "name": p.get("name"),
            "brand": p.get("brand"),
            "price": p.get("sizes", [{}])[0].get("price", {}).get("product", 0) / 100,
            "rating": p.get("rating", 0),
            "feedbacks": p.get("feedbacks", 0)
        }
        items.append(item)

    df = pd.DataFrame(items)

    if df.empty:
        await message.answer("По вашему запросу товаров не найдено.")
        return

    # 1. Гистограмма цен
    plt.figure(figsize=(8,5))
    sns.histplot(df['price'], bins=20, kde=True)
    plt.title("Распределение цен")
    plt.xlabel("Цена, руб")
    plt.ylabel("Количество товаров")
    price_buf = io.BytesIO()
    plt.savefig(price_buf, format='png')
    price_buf.seek(0)
    plt.close()

    # 2. Топ-10 брендов по количеству
    top_brands = df['brand'].value_counts().head(10)
    plt.figure(figsize=(8,5))
    sns.barplot(x=top_brands.index, y=top_brands.values)
    plt.title("Топ-10 брендов по количеству товаров")
    plt.xlabel("Бренд")
    plt.ylabel("Количество")
    plt.xticks(rotation=45)
    brands_count_buf = io.BytesIO()
    plt.savefig(brands_count_buf, format='png')
    brands_count_buf.seek(0)
    plt.close()

    # 3. Топ-10 брендов по средней цене
    brand_price = df.groupby('brand')['price'].mean().sort_values(ascending=False).head(10)
    plt.figure(figsize=(8,5))
    sns.barplot(x=brand_price.index, y=brand_price.values)
    plt.title("Топ-10 брендов по средней цене")
    plt.xlabel("Бренд")
    plt.ylabel("Средняя цена, руб")
    plt.xticks(rotation=45)
    brands_avg_price_buf = io.BytesIO()
    plt.savefig(brands_avg_price_buf, format='png')
    brands_avg_price_buf.seek(0)
    plt.close()

    # Отправляем все 3 графика 
    await message.answer_photo(types.BufferedInputFile(price_buf.getvalue(), filename='price.png'))
    await message.answer_photo(types.BufferedInputFile(brands_count_buf.getvalue(), filename='brands_count.png'))
    await message.answer_photo(types.BufferedInputFile(brands_avg_price_buf.getvalue(), filename='brands_avg_price.png'))

async def on_start():
    await bot.delete_webhook(drop_pending_updates=True)
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(on_start())

3.3. Что умеет бот

  1. По команде /search <запрос>; собирает товары Wildberries.

  2. Формирует три графика:

    • распределение цен,

    • топ-10 брендов по количеству товаров,

    • топ-10 брендов по средней цене.

  3. Отправляет графики в PNG, готовые для анализа

Получаем данные парсинга в боте
Получаем данные парсинга в боте

Код и графики дают базовую аналитику, но пространство для улучшений огромное: можно парсить больше страниц, анализировать отзывы, интегрировать и с другими сервисами.

Шаг 4. Деплой в Amvera

Итак, когда у нас уже есть что-то, мы можем перейти к деплою бота.

Регистрация в Amvera

Как ни странно, для начала нужно зарегистрироваться по ссылке. Сразу после регистрации вы получите 111 рублей для тестов. Этого будет достаточно для того, чтобы довести проект до ума и некоторое время подержать приложение бесплатно.

Создание проекта

На главной странице жмем кнопку "Создать проект" и действуем по инструкции ниже:

Шаги создания проекта
  1. Выбор сервиса

    1.1 Тип сервиса: Приложение

    1.2 Жмём далее.

  2. Тариф

    2.1 Название проекта: произвольное

    2.2 Выберите тариф: рекомендуется использовать тариф не ниже "Начального".

  3. Загрузка данных.

    3.1 На этом шаге вы можете привязать локальный репозиторий Git, если будете использовать его. Об этом поговорим чуть позже.

    3.2 Рекомендуется пропустить этот шаг и загрузить данные после создания проекта. 3.3 Жмём далее.

  4. Переменные

    4.1 Переменные окружения создадим позже. Жмём далее

  5. Конфигурация

    5.1 Аналогично с переменными, создадим их позже.

  6. Завершаем создание проекта и переходим на его страницу.

Загрузка данных

Теперь у нас есть выбор как загружать данные:

  1. Через интерфейс. Удобно, если вдальнейшем не планируете часто обновлять проект.

  2. Через пуш в git-репозиторий Amvera. Самый удобный способ, если ведете разработку в одиночку.

  3. Через пуш в репозиторий стороннего Git-сервиса (например, GitHub). Удобно, если работаете в команде.

Сейчас же мы загрузим данные через интерфейс.

Однако, если вы планируете использовать второй или третий способ, следуйте инструкциям ниже:

Загружаем в корень Code два файла:

Создание конфигурации

Для сборки и запуска приложения, сервису нужны инструкции, которые мы пропишем в файл конфигурации - amvera.yml.

Самостоятельно файл создавать не нужно, достаточно воспользоваться встроенным во вкладку "Конфигурация" конфигуратором и нажать кнопку "Применить".

Просто пропишите следующие значения параметров:

Задание конфигурации парсера
Задание конфигурации парсера

Создание переменных окружения

Amvera поддерживает два типа переменных:

  • Секрет. Чаще всего используется для токенов ботов и любых других конфиденциальных данных. Именно его мы и создадим. Его особенность в том, что никто кроме вашего проекта не видит значение переменной.

  • Переменная окружения. Обычная переменная. Видна всем, у кого есть доступ к ЛК (извне не видно никому).

Создадим секрет TOKEN во вкладке "Переменные".

Зададим токен в секрете
Зададим токен в секрете

Сборка и запуск проекта

Если вы все сделали по инструкции, то все готово к первой сборке и запуску. Для этого нужно лишь перейти во вкладку "Конфигурация" и нажать кнопку "Собрать". После этого начнется процесс сборки и запуска.

Если у вас возникли сложности при запуске или сборке - обращайтесь в техническую поддержку.
https://t.me/amverachat
support@amvera.ru

Итог

В этой статье мы разобрали, как собрать и проанализировать данные о товарах и ценах с Wildberries и реализовали:

  1. Парсинг данных — через внутренние API Wildberries, получая JSON с товарами, брендами, ценами, рейтингами и отзывами.

  2. Обработку и визуализацию — с помощью pandas, matplotlib и seaborn можно строить таблицы и графики для анализа конкурентов.

  3. Автоматизацию через Telegram-бота — бот позволяет быстро получать аналитику по любому запросу прямо в чат, с готовыми графиками.

  4. Деплой в облако Amvera — проект можно легко запустить и тестировать в облачном окружении без лишних настроек.

Это именно демонстрационный пример, на основе которого можно реализовать собственный парсер цен конкурентов.


Релевантные статьи и страницы документации:

Комментарии (0)


  1. Data4
    21.09.2025 08:58

    А какие ограничения у данного подхода парсинга? Обычно крупные маркетплейсы, как Wildberries не любят, когда много информации с них парсят


    1. MarkovM Автор
      21.09.2025 08:58

      В данной реализации парсинга, лучше ограничивать количество запросов, иначе будет прилетать 429 ошибка.


  1. VladimirFarshatov
    21.09.2025 08:58

    В парсерах надо обязательно ограничивать частоту запросов, делая паузы в 3-10сек между не более десятком запросов. В противном случае ИБ заблокирует ваш ИП как ДДОС и достаточно быстро, автоматами контроля за нагрузкой сайтов. Поэтому и прилетает 429.