Zalando, один из крупнейших ритейлеров моды в Европе, а публичные страницы товаров содержат именно те структурированные данные, которые питают мониторинг цен, отслеживание ассортимента и исследование модных тенденций: названия товаров, бренды, цены, доступные размеры и цвета. Проблема в том, что Zalando отрисовывает эти страницы с помощью JavaScript и жёстко защищается от ботов, поэтому обычный HTTP-запрос выдаёт пустую оболочку или страницу проверки вместо нужного каталога.
В этом руководстве показано, как надёжно создать скрапер Zalando на Python. Вы получаете полностью отрисованные страницы товаров через Crawling API с JavaScript-токеном, парсите разметку с помощью BeautifulSoup и извлекаете нужные поля. Всё руководство ограничено публичными данными о товарах, а раздел о законности в конце не является шаблонным, поэтому прочитайте его перед тем, как направлять скрапер на реальные объёмы.
Что вы создадите
Скрипт Python, который принимает публичный URL товара Zalando, получает отрисованный HTML через Crawling API и извлекает структурированную запись об элементе. В качестве текущего примера мы используем одну страницу товара и извлекаем следующие поля:
- Product name название товара, например "Leather Handbag".
- Brand бренд товара, например "Zign".
- Price текущая цена продажи, включая валюту.
- Available sizes размеры, показанные как доступные на странице.
- Color цветовая вариация перечисленного варианта.
После того как одна страница работает, мы перебираем список URL товаров и контролируем темп запросов, чтобы реальная задача оставалась работоспособной. Каталог моды, это классическая цель ecommerce web scraping, и паттерн здесь переносится на большинство ритейлеров.
Почему обычный запрос не работает на Zalando
Если запросить URL товара Zalando с помощью обычного HTTP-клиента, вы получите один из двух бесполезных ответов: статус 200 почти без данных о товаре в теле, или бот-проверку. Против вас работают два фактора. Во-первых, Zalando отрисовывает содержимое товара в браузере с помощью JavaScript, поэтому исходный HTML является оболочкой, заполняющейся только после выполнения скриптов страницы. Во-вторых, Zalando быстро помечает автоматизированный трафик: IP-адреса дата-центров и шаблоны запросов, не похожие на настоящий браузер, блокируются ещё до того, как когда-либо достигнут отрисованного контента.
Поэтому рабочий скрапер Zalando должен совмещать два требования в одном запросе: браузер, реально отрисовывающий страницу, и IP-адрес, который платформа воспринимает как настоящего пользователя. Вы можете собрать всё это самостоятельно с headless-браузером и пулом ротируемых резидентских прокси, но объединение и поддержка этих компонентов и составляет основную часть работы. Crawling API объединяет оба в один вызов: вы передаёте ему URL с JavaScript-токеном, он отрисовывает страницу за надёжным IP-адресом и возвращает готовый HTML для парсинга. Если вам нужна информация о том, почему клиентский рендеринг ломает наивные скраперы, см. как краулить JavaScript-сайты.
Crawlbase предлагает два типа токенов. Обычный токен получает статический HTML; JavaScript (JS) токен сначала отрисовывает страницу в настоящем браузере. Zalando рендерится на стороне клиента, поэтому здесь нужен JS-токен. Использование обычного токена возвращает ту же пустую оболочку, что и обычный запрос, и из неё нечего полезного парсить.
Предварительные требования
Перед написанием кода вам понадобится несколько вещей. Ни одна из них не займёт много времени.
Базовые знания Python. Вы должны уметь писать и запускать скрипты Python и устанавливать пакеты с помощью pip. Если BeautifulSoup для вас нова, наше руководство по BeautifulSoup на Python охватывает основы парсинга, которые предполагает данный учебник.
Python версии 3.8 или новее. Проверьте свою версию командой python --version. Если у вас её нет, установите с python.org или через дистрибутив вроде Anaconda.
Аккаунт Crawlbase и JS-токен. Зарегистрируйтесь, откройте панель управления и скопируйте свой JavaScript (JS) токен со страницы документации аккаунта. Относитесь к токену как к паролю: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.
Настройка проекта
Создайте виртуальное окружение, чтобы зависимости проекта оставались изолированными, а затем установите две библиотеки, необходимые скраперу.
python --version python -m venv zalando_env source zalando_env/bin/activate pip install crawlbase beautifulsoup4
В Windows активируйте окружение командой zalando_env\Scripts\activate вместо строки с source. Две зависимости выполняют основную работу: crawlbase является официальным клиентом для Crawling API, а beautifulsoup4 парсит возвращаемый HTML, позволяя извлекать отдельные поля по CSS-селекторам.
Шаг 1: Получение отрисованной страницы товара
Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его вашим JS-токеном и запросите URL товара. Проверка кода состояния перед парсингом делает ошибки явными, а не скрытыми.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def crawl(page_url): options = {"ajax_wait": "true", "page_wait": 5000} response = api.get(page_url, options) if response["status_code"] == 200: return response["body"].decode("utf-8") print(f"Request failed: {response['status_code']}") return None if __name__ == "__main__": page_url = "https://en.zalando.de/zign-handbag-black-zi151h08a-q11.html" html = crawl(page_url) print(html[:500] if html else "No HTML returned")
Два параметра ожидания важны для клиентски-рендеримой цели вроде этой. ajax_wait указывает API ждать завершения загрузки асинхронного контента, а page_wait выдерживает фиксированное количество миллисекунд после загрузки, чтобы элементы с поздним рендерингом появились до захвата страницы. Пяти секунд достаточно для начала; увеличьте значение, если поля товара возвращаются пустыми. Запустите скрипт командой python scraper.py, и вы должны увидеть настоящую разметку товара, а не пустую оболочку от обычного запроса. Это подтверждает работу рендеринга ещё до написания первого селектора.
Zalando требует отрисованной страницы за надёжным IP-адресом в одном вызове. Crawling API принимает JS-токен, запускает страницу в настоящем браузере, ротирует резидентские IP-адреса на стороне сервера и передаёт вам готовый HTML, поэтому вам не нужно самостоятельно запускать headless-флот и пул прокси. Сначала направьте его на публичную страницу товара в бесплатном тарифе.
Шаг 2: Парсинг полей товара с BeautifulSoup
Получив отрисованный HTML, загрузите его в BeautifulSoup и извлеките каждое поле по его селектору. Страницы товаров Zalando имеют довольно предсказуемую структуру для основных деталей, поэтому вы можете сопоставить название, бренд, цену, размеры и цвет с отдельными селекторами. Оборачивайте извлечение в вспомогательные функции, чтобы отсутствие одного поля не останавливало выполнение.
from bs4 import BeautifulSoup def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def all_text(soup, selector): return [el.get_text(strip=True) for el in soup.select(selector)] def scrape_product(html): soup = BeautifulSoup(html, "html.parser") sizes = all_text(soup, "[data-testid='pdp-size-picker'] [role='option']") return { "name": text_of(soup, "span.EKabf7.R_QwOV"), "brand": text_of(soup, "span.OBkCPz.Z82GLX"), "price": text_of(soup, "span.voFjEy.Km7l2y"), "color": text_of(soup, "[data-testid='color-name']"), "sizes": [s for s in sizes if s], }
Вспомогательная функция text_of делает две полезные вещи сразу: она запрашивает один элемент и возвращает None, когда элемент отсутствует, вместо того чтобы выбрасывать исключение на вызов .get_text() к пустому значению. Вспомогательная функция all_text собирает все совпадения для полей, которые повторяются, что нужно для вариантов размеров. Это делает извлечение устойчивым при отсутствии одного поля на данной странице, что часто встречается, так как не каждый товар перечисляет все детали.
Хешированные имена классов Zalando (токены вроде EKabf7 и voFjEy) генерируются и меняются без предупреждения. Относитесь к приведённым выше селекторам как к стартовому шаблону, а не как к контракту. Когда поле возвращается как None или пустой список, повторно осмотрите живую страницу в DevTools браузера и обновите селектор. Стабильные атрибуты data-testid, как правило, переживают хешированные имена классов, поэтому предпочитайте их там, где они есть. Периодическое обслуживание селекторов является нормой для любого рабочего скрапера, а не признаком поломки.
Шаг 3: Сборка воедино
Теперь объедините получение и парсинг в один работоспособный скрипт. Получите отрисованный HTML, передайте его парсеру и выведите структурированную запись.
import json from crawlbase import CrawlingAPI from bs4 import BeautifulSoup api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def crawl(page_url): options = {"ajax_wait": "true", "page_wait": 5000} response = api.get(page_url, options) if response["status_code"] == 200: return response["body"].decode("utf-8") print(f"Request failed: {response['status_code']}") return None def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def all_text(soup, selector): return [el.get_text(strip=True) for el in soup.select(selector)] def scrape_product(html): soup = BeautifulSoup(html, "html.parser") sizes = all_text(soup, "[data-testid='pdp-size-picker'] [role='option']") return { "name": text_of(soup, "span.EKabf7.R_QwOV"), "brand": text_of(soup, "span.OBkCPz.Z82GLX"), "price": text_of(soup, "span.voFjEy.Km7l2y"), "color": text_of(soup, "[data-testid='color-name']"), "sizes": [s for s in sizes if s], } def main(): page_url = "https://en.zalando.de/zign-handbag-black-zi151h08a-q11.html" html = crawl(page_url) if not html: return data = scrape_product(html) print(json.dumps(data, indent=2, ensure_ascii=False)) if __name__ == "__main__": main()
Установка ensure_ascii=False при дампе JSON сохраняет знак евро и любые символы с акцентами читаемыми, а не экранированными. Запустите полный скрипт командой python scraper.py, и вы получите чистую структурированную запись о товаре.
Как выглядит результат
Скрипт выводит одну запись, готовую для записи в JSON, CSV или базу данных.
{ "name": "LEATHER - Handbag", "brand": "Zign", "price": "49,99 €", "color": "black", "sizes": ["One Size"] }
Для одежды список sizes будет содержать реальный набор размеров, например ["XS", "S", "M", "L"], с исключёнными распроданными размерами, если вы фильтруете по состоянию доступности в средстве выбора размера.
Масштабирование на множество товаров
Одна страница, это демонстрация; реальная задача выполняется по списку товаров. Форма остаётся той же: ведите список URL товаров, получайте каждый через Crawling API, парсите той же функцией и собирайте строки. Поскольку каждая страница товара имеет одинаковую структуру, уже написанный парсер работает для всех них без изменений. Ключевое добавление, это темп: короткая пауза между запросами не позволяет запуску выглядеть как всплеск бот-трафика.
import time products = [ "https://en.zalando.de/zign-handbag-black-zi151h08a-q11.html", "https://en.zalando.de/anna-field-handbag-black-an651h0x2-q11.html", ] results = [] for url in products: html = crawl(url) if html: results.append({"url": url, **scrape_product(html)}) time.sleep(2) with open("zalando_products.json", "w", encoding="utf-8") as f: json.dump(results, f, indent=2, ensure_ascii=False)
Чтобы найти URL товаров в масштабе, скрапьте публичные страницы каталога Zalando (например, https://en.zalando.de/catalogue/?q=handbags) с тем же паттерном «получить-затем-парсить», собирайте ссылки на товары, а затем посещайте каждую. Просто держите объём разумным и соблюдайте ограничения частоты запросов, описанные ниже. Если цена является вашей конечной целью, собранные записи напрямую питают конвейер ценовой аналитики.
Оставаться незаблокированным
Даже при обработанном рендеринге Zalando отслеживает трафик, похожий на скрапинг. Несколько привычек поддерживают работоспособность запуска, и они применимы к любой сложной коммерческой цели.
-
Соблюдайте темп запросов. Bombardировка страниц в плотном цикле, это самый быстрый способ получить ограничение. Приведённый выше
time.sleepраспределяет запросы; варьируйте цели вместо краулинга одного пути на полной скорости. - Полагайтесь на ротацию. Пул резидентских IP-адресов распределяет запросы по множеству адресов реальных пользователей, так что ни один из них не превышает лимит. Crawling API делает это за вас; если вы используете собственный стек, именно здесь нужно сделать всё правильно.
- Читайте коды состояния. Запуск, который начинает возвращать проверки или ошибки, сообщает вам, что текущей частоты или уровня IP уже недостаточно. Воспринимайте это как сигнал снизить скорость, а не как шум, который нужно игнорировать.
Более широкое руководство см. в статьях о том, как скрапить сайты, не попадая в блок, и о том, как обходить CAPTCHA при веб-скрапинге. Если вы предпочитаете маршрутизировать собственный трафик через ротируемый пул, а не использовать управляемый API, Smart AI Proxy (также называемый AI Proxy) предоставляет ту же ротацию резидентских IP в виде сменного прокси-эндпоинта. Тот же подход распространяется на соседние каталоги, такие как AliExpress и Walmart.
Законно ли скрапить Zalando?
Допустимость скрапинга Zalando зависит от условий использования сервиса, вашей юрисдикции и того, что вы делаете с данными. Условия Zalando ограничивают автоматизированный доступ, поэтому скрапинг может противоречить им независимо от того, насколько осторожен ваш инструментарий. Ни один из приведённых здесь кодов не меняет этого; он просто заставляет техническую часть работать. Прочтите Условия использования Zalando и его robots.txt и рассматривайте оба документа как границу того, что вы собираете.
Несколько правил, которых стоит придерживаться. Собирайте только публичные данные о товарах: название, бренд, цену, доступные размеры и цвет, которые любой может видеть без аккаунта. Соблюдайте ожидаемую Zalando частоту запросов и поддерживайте объём достаточно низким, чтобы не нагружать серверы. Избегайте персональных данных, включая всё, что связано с идентифицируемыми людьми, например профили рецензентов или данные аккаунтов. Если вы планируете коммерческое использование данных, получите разрешение или официальное соглашение, а не предполагайте, что молчание означает согласие.
Это руководство намеренно ограничено публичными страницами товаров, поскольку именно это позволяет сохранить работу защищённой. Оно не охватывает ничего за логином, данные аккаунтов или заказов, персональные данные, страницы за аутентификацией или попытки обойти авторизацию. Для крупномасштабного или коммерческого использования предпочтите официальный API или соглашение об обмене данными с Zalando, а не более хитрый скрапер. Только публичные данные о товарах, вот правило, которое держит вас в рамках как условий, так и закона.
Ключевые выводы
- Zalando рендерится на стороне клиента. Обычный запрос возвращает пустую оболочку или проверку, поэтому необходимо отрисовать страницу перед её парсингом.
-
Вам нужны рендеринг и надёжный IP вместе. Crawling API с JS-токеном делает и то и другое в одном вызове;
ajax_waitиpage_waitуправляют временем ожидания контента. -
BeautifulSoup выполняет извлечение. Сопоставьте название товара, бренд, цену, размеры и цвет с текущими селекторами, предпочитайте стабильные атрибуты
data-testidи ожидайте дрейфа хешированных имён классов. - Масштабируйтесь через перебор URL с контролем темпа. Тот же парсер работает для каждого товара, поэтому реальная задача, это просто список ссылок плюс короткая пауза между запросами.
- Держитесь публичных данных. Соблюдайте ToS и robots.txt Zalando, предпочитайте официальный API для объёмного или коммерческого использования и никогда не касайтесь аккаунтов, страниц за аутентификацией или персональных данных.
Часто задаваемые вопросы
Почему обычный запрос не возвращает данных от Zalando?
Потому что Zalando отрисовывает содержимое товаров на стороне клиента с помощью JavaScript. Исходный HTML является оболочкой, заполняющейся только после выполнения скриптов страницы в браузере, поэтому сырой HTTP-запрос возвращает статус 200 с пустыми полями товара или бот-проверку вместо страницы. Чтобы получить реальные данные, необходимо сначала отрисовать страницу, что и берёт на себя JS-токен Crawling API.
Нужен ли мне обычный токен или JS-токен для Zalando?
JS-токен. Обычный токен получает статический HTML, который на Zalando представляет собой ту же пустую оболочку, что и обычный запрос. JS-токен отрисовывает страницу в настоящем браузере перед возвратом HTML, поэтому название товара, бренд, цена, размеры и цвет присутствуют при парсинге BeautifulSoup.
Мои селекторы возвращают None или пустые списки. Что изменилось?
Скорее всего, разметка Zalando. Хешированные имена классов вроде EKabf7 и voFjEy генерируются и меняются без предупреждения, поэтому ранее работавшие селекторы могут сломаться. Повторно осмотрите живую страницу товара в DevTools браузера и обновите селекторы. Предпочитайте стабильные атрибуты data-testid там, где они есть, поскольку они переживают редизайны дольше, чем хешированные классы.
Могу ли я использовать Python вместо Puppeteer или Node.js для скрапинга Zalando?
Да. Поскольку Crawling API отрисовывает страницу на стороне сервера и возвращает готовый HTML, вам вовсе не нужно запускать headless-браузер локально. Небольшого скрипта Python с клиентом crawlbase и BeautifulSoup достаточно, что и является всем подходом в этом руководстве. Это делает скрапер лёгким и легко планируемым.
Как скрапить много товаров Zalando, не попадая в блок?
Держите частоту запросов на один IP низкой, добавляйте короткую паузу между запросами и варьируйте цели вместо цикличного прохода по одному пути. Маршрутизируйте через ротируемые резидентские IP, чтобы ни один адрес не превышал лимит; Crawling API управляет ротацией и надёжным пулом IP за вас. Следите за кодами состояния и снижайте скорость при появлении проверок.
Законно ли скрапить данные о товарах Zalando?
Это зависит от условий использования Zalando, вашей юрисдикции и вашего сценария использования данных. Это руководство ограничено публичными данными о товарах (название, бренд, цена, размеры, цвет) и просит вас соблюдать robots.txt и ToS. Оно не охватывает данные аккаунтов, персональные данные, страницы за аутентификацией или обход авторизации. Для объёмного или коммерческого использования официальный API или соглашение об обмене данными является правильным путём, а не скрапер.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
