За полтора года практики я собирал парсер Ozon с выгрузкой в Excel для десятка разных заказчиков - от перекупов, которые сверяют цены конкурентов раз в сутки, до владельцев интернет-магазинов на WooCommerce, которым нужна еженедельная выгрузка ассортимента по нескольким тысячам SKU. Ниже - рабочий код на Python, разбор ошибок, с которыми реально сталкивался (403, капча вместо страницы, пустые ответы из-за клиентского рендеринга), и что делать, чтобы выгрузка не отваливалась уже после третьего запуска.
Что можно вытащить с Ozon и зачем это вообще нужно
Ozon отдаёт на карточке товара куда больше, чем видно глазом: название, цену (обычную и по карте/акции), рейтинг, число отзывов, наличие на складах, характеристики, идентификатор продавца. Из категории или поиска можно выгрузить список SKU целиком - это отправная точка почти любого парсера.
На практике запросы делятся на три группы:
- мониторинг цен конкурентов - нужен, чтобы репрайсер или менеджер вручную корректировал наценку;
- сбор отзывов и рейтингов - для анализа спроса перед выводом новой позиции в ассортимент;
- выгрузка своего же каталога - сверка с прайсом на сайте или в учётной системе.
Один из клиентов держит магазин на WooCommerce и раз в сутки сравнивает свои цены с ценами трёх конкурентов на Ozon - выгрузка в Excel идёт прямо в таблицу, по которой менеджер решает, где скорректировать наценку. Без парсера это отслеживание отнимало у него часа полтора в день.
API Ozon Seller и HTML-парсинг - разные задачи
Seller API у Ozon есть, но он открывает данные только по собственному кабинету продавца - свои заказы, остатки, цены, аналитику. Для конкурентной разведки или сбора чужого каталога он бесполезен: чтобы узнать цену на товар конкурента, доступ только один - разбирать HTML страницы или перехватывать её внутренние JSON-запросы.
Разница между вариантами:
| Вариант | Что даёт | Когда использовать |
|---|---|---|
| Seller API | Данные своего кабинета: заказы, остатки, цены | Автоматизация своего магазина на Ozon |
| requests + BeautifulSoup | Разбор отданного HTML/JSON без браузера | Когда нужные поля есть в исходном коде страницы |
| Playwright/Selenium | Полный рендеринг страницы, как в браузере | Когда данные подгружаются через JS после загрузки |
На практике страница товара Ozon отдаёт большую часть данных сразу в HTML - они зашиты в JSON внутри тега script (маркетплейс использует серверный рендеринг и передаёт состояние приложения прямо в разметке). Поэтому в большинстве случаев хватает requests и BeautifulSoup, без headless-браузера - это быстрее в 5-10 раз и не требует Chromium на сервере. Playwright подключаю, только если нужно долистать бесконечную ленту отзывов или каталог подгружает товары через infinite scroll.
Пишем парсер Ozon с выгрузкой в Excel: рабочий код
Ниже - упрощённая, но рабочая версия того, что использую в проектах: собираем список карточек товаров, вытаскиваем название, цену, рейтинг и число отзывов, пишем результат в Excel через openpyxl.
import re
import json
import time
import random
from openpyxl import Workbook
import requests
from bs4 import BeautifulSoup
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/124.0 Safari/537.36",
"Accept-Language": "ru-RU,ru;q=0.9",
}
def get_product_data(url):
resp = requests.get(url, headers=HEADERS, timeout=15)
if resp.status_code != 200:
raise RuntimeError(f"Ozon ответил {resp.status_code} на {url}")
soup = BeautifulSoup(resp.text, "html.parser")
script = soup.find("script", string=re.compile("priceRegular"))
if not script:
raise ValueError("Не нашёл JSON с данными — вероятно, отдана капча")
data = json.loads(script.string)
return {
"name": data.get("name"),
"price": data.get("priceRegular"),
"rating": data.get("rating"),
"reviews": data.get("reviewsCount"),
}
def parse_and_export(urls, out_path="ozon_export.xlsx"):
wb = Workbook()
ws = wb.active
ws.append(["Название", "Цена", "Рейтинг", "Отзывы", "URL"])
for url in urls:
try:
item = get_product_data(url)
ws.append([item["name"], item["price"], item["rating"], item["reviews"], url])
except Exception as e:
ws.append(["ОШИБКА", str(e), "", "", url])
time.sleep(random.uniform(2, 5))
wb.save(out_path)
if __name__ == "__main__":
urls = [
"https://www.ozon.ru/product/example-1",
"https://www.ozon.ru/product/example-2",
]
parse_and_export(urls)
Несколько моментов, на которые обращаю внимание:
- признак данных в script-теге Ozon периодически меняет - поэтому ищу не по фиксированному id, а по содержимому (по полю priceRegular);
- пауза
time.sleep(random.uniform(2, 5))между запросами - без неё блокировка по IP прилетает уже после 20-30 запросов подряд; - ошибки не роняют весь скрипт - каждая проблемная строка попадает в Excel с пометкой «ОШИБКА» и текстом причины, чтобы потом отфильтровать и перезапустить точечно.
Если не хочется собирать это с нуля, у меня в библиотеке готовых скриптов есть шаблон в похожей логике - можно адаптировать под свой список категорий за пару часов вместо пары дней.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Разбор типичных ошибок при парсинге Ozon
На проектах чаще всего вижу одни и те же четыре проблемы:
| Ошибка | Причина | Что делать |
|---|---|---|
| 403 Forbidden сразу на первом запросе | Дефолтные заголовки requests слишком похожи на бота | Полный набор заголовков как у браузера, ротация User-Agent |
| 429 или пустой ответ через 20-40 запросов | Сработал рейт-лимит по IP | Пауза 2-5 секунд между запросами, прокси при больших объёмах |
| KeyError / None вместо цены | Ozon обновил разметку, изменилась структура JSON | try/except на уровне одной карточки, а не всего скрипта |
| Вместо HTML пришла капча | Слишком частые запросы с одного IP, нет cookies сессии | Прокси плюс «разогрев» сессии - сначала главная, потом карточка |
Самая частая причина, почему парсер «работал вчера, а сегодня падает» - верстка маркетплейса не статична, разработчики Ozon меняют структуру данных без предупреждения. Я закладываю в код обработку ошибок на уровне каждой карточки отдельно, чтобы одна сломанная страница не обрушила всю выгрузку на тысячу позиций.
Как снизить число блокировок при сборе данных с Ozon
Заголовки и паузы решают базовый уровень защиты, но при объёме от пары тысяч карточек в день без прокси почти не обойтись. Использую резидентные или мобильные прокси, а не дата-центровые - последние Ozon вычисляет по подсетям почти сразу. Переиспользую cookies в рамках одной сессии, ограничиваю число запросов в минуту и добавляю ретраи с экспоненциальной задержкой на 429 и 5xx-ответах.
На одном проекте выгрузка 5000 карточек без прокси падала на 400-500‑й позиции стабильно. Добавил ротацию из пяти резидентных прокси и паузу 3-4 секунды - дошли до 5000 без единой капчи, но прогон занял почти 4 часа вместо 40 минут. Такой компромисс стоит закладывать в оценку сроков сразу, а не обещать клиенту выгрузку каталога за час.
Автоматизация выгрузки: расписание, Telegram и n8n
Разовый прогон скрипта руками нормален для теста, но для регулярного мониторинга нужен планировщик. Варианты, которые использую:
- Windows Task Scheduler или cron на Linux-сервере - если выгрузка нужна раз в день по расписанию;
- n8n с нодой запуска команды - забирает готовый xlsx и сразу отправляет его на почту или в облачное хранилище без ручного вмешательства;
- Telegram-бот на aiogram - присылает файл по команде или по кнопке, удобно, когда за выгрузкой должен приходить не разработчик, а менеджер без доступа к серверу.
Для клиента с магазином на WooCommerce собрал именно такую связку: cron раз в сутки запускал парсер, n8n забирал готовый Excel и складывал в общую папку, а менеджер получал уведомление в Telegram, что файл обновился. Ручной работы у него не осталось вообще, кроме самой корректировки цен по итоговой таблице.
Данные и процессы на автопилоте
Парсинг / Автоматизация
от 20 000 ₽
Подробнее →Частые вопросы
Не забанит ли Ozon за парсинг каталога?
Блокировка обычно точечная - по IP или сессии, а не по аккаунту, потому что сбор данных идёт без авторизации в личном кабинете. При адекватных паузах и прокси риск минимален, но полностью исключить временную капчу нельзя - это обычная часть работы с любым маркетплейсом, а не признак того, что скрипт написан плохо.
Сколько стоит парсер Ozon под ключ?
Собственные проекты по парсингу и автоматизации на Python у меня стоят от 20 000 ₽ - итоговая цена зависит от количества полей, частоты запуска и того, нужна ли интеграция с Excel, 1С или CRM на выходе. На бирже фриланса и в студиях за похожую задачу просят от 15 000 до 50 000 ₽, но там сильно зависит от того, включена ли доработка после первого запуска в цену или идёт отдельно.
Можно ли парсить Ozon без прокси?
Для 100-300 карточек в день обычно да, если выдерживать паузы и не долбить с одного IP слишком часто. Для тысяч позиций или ежедневного мониторинга без прокси почти гарантированно упрётесь в капчу или временную блокировку уже через 20-40 минут работы.
Как часто можно обновлять выгрузку в Excel?
Для мониторинга цен конкурентов хватает одного прогона в сутки - цены на Ozon не скачут каждый час. Для складских остатков в высокий сезон, перед распродажами или в декабре, интервал стоит сократить до 2-3 раз в день, но тогда нужен более аккуратный график запросов, чтобы не спалить IP раньше времени.