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

В этом руководстве показано, как парсить листинги Shein с помощью Python. Вы создадите небольшой работающий парсер, который загружает страницу категории или поиска Shein через Crawling API, разбирает структурированную запись для каждого товара, обрабатывает пагинацию и экспортирует результаты в JSON и CSV. Всё руководство ограничено публичными данными листинга: названиями товаров, ценами, рейтингами и ссылками, доступными любому посетителю страницы листинга Shein без входа в систему.

Что вы создадите

Python-скрипт, который принимает URL категории или поиска Shein, загружает отрендеренную страницу через Crawling API и извлекает структурированную запись по каждому товару в сетке. В качестве рабочего примера используется страница категории женской одежды. Из каждой карточки товара парсер извлекает следующие поля:

  • Title название товара, отображаемое на карточке листинга.
  • Price текущая цена продажи, если она указана на карточке.
  • Rating средний звёздный рейтинг, отображаемый на карточке.
  • Link абсолютный URL страницы с подробными сведениями о товаре.
  • Image URL изображения товара из миниатюры карточки.

Эти поля напрямую соответствуют тем, что собирал прежний вариант руководства (название товара, цена, рейтинги и URL изображений), сокращённым до того, что реально отображает сетка листинга. Детали конкретного товара, такие как артикул, полное описание, цвета и размеры, находятся на отдельной странице товара, на которую можно перейти по полю link и разобрать её аналогичным образом.

Почему обычный запрос не работает на Shein

Если направить простой HTTP-клиент на URL категории Shein, в большинстве случаев вы не получите искомую сетку товаров. Здесь есть два препятствия. Во-первых, Shein рендерит листинги на стороне клиента: сервер отправляет лёгкую оболочку, а карточки товаров появляются по мере выполнения JavaScript страницы и прокрутки, поэтому первоначальный HTML почти не содержит товаров. Библиотека, которая читает только первый HTTP-ответ без браузера для выполнения скриптов, видит практически пустую страницу.

Во-вторых, Shein отслеживает автоматизированный трафик. Диапазоны IP-адресов датацентров и паттерны запросов, не похожие на поведение реального покупателя, получают в ответ страницу-вызов, региональное перенаправление или полную блокировку ещё до достижения сетки товаров. Таким образом, работающий парсер Shein требует двух вещей в одном запросе: браузера, который рендерит страницу, и IP-адреса, который Shein воспримет как реального посетителя. Можно собрать такой стек самостоятельно с помощью headless-браузера и пула ротируемых резидентских прокси, но поддержание этого стека в рабочем состоянии занимает большую часть времени. Crawling API объединяет оба требования в одном вызове: вы отправляете URL листинга, он рендерит страницу за доверенным резидентским IP, управляет ротацией и любым вызовом и возвращает готовый HTML для разбора.

Предварительные требования

Перед написанием кода необходимо подготовить несколько вещей. Ни одна из них не займёт много времени.

Базовые знания Python. Вы должны уметь писать и запускать Python-скрипты, а также устанавливать пакеты с помощью pip. Если вы только начинаете изучать язык, официальная документация Python или любой вводный курс охватывает уровень, который предполагает это руководство; наш гайд по использованию BeautifulSoup в Python подробно рассматривает библиотеку парсинга.

Python 3.8 или выше. Проверьте версию командой python --version (или python3 --version). Если Python не установлен, скачайте его с python.org и убедитесь, что он добавлен в PATH.

Аккаунт и токен Crawlbase. Зарегистрируйтесь, откройте панель управления и скопируйте токен со страницы документации аккаунта. Бесплатный уровень включает до 20 000 запросов без привязки карты, этого достаточно для создания и тестирования парсера. Shein требует JavaScript-токен, поскольку листинг рендерится на стороне клиента. Храните токен как пароль и не добавляйте его в систему контроля версий.

Настройка проекта

Создайте виртуальное окружение для изоляции зависимостей проекта, затем установите две необходимые библиотеки. crawlbase, официальный клиент для Crawling API, а beautifulsoup4 разбирает возвращённый HTML, позволяя извлекать каждое поле из карточек товаров по CSS-селектору.

bash
python --version

python -m venv shein_env
source shein_env/bin/activate

pip install crawlbase beautifulsoup4

В Windows активируйте окружение командой shein_env\Scripts\activate вместо строки с source. После установки обеих библиотек создайте файл скрипта, который будет наполняться по мере прохождения руководства:

bash
touch shein_listing.py

Понимание страницы листинга

Листинг Shein находится по URL категории, например https://www.shein.com/Women-Clothing-c-2030.html, или по URL поиска вида https://www.shein.com/pdsearch/dress/. Оба типа отображают сетку карточек товаров, по одной на каждый товар, каждая из которых содержит одинаковый набор полей: миниатюру изображения, название, цену, необязательный звёздный рейтинг и ссылку на страницу товара.

Прежде чем писать селекторы, откройте страницу листинга в браузере, щёлкните правой кнопкой мыши по карточке товара и выберите «Просмотр кода». Shein оборачивает каждый товар в секцию с атрибутом class, содержащим product-card, размещает название в элементе-ссылке или имени, показывает цену в специальном элементе цены и раскрывает миниатюру и ссылку на товар внутри этого контейнера. Именно эти элементы вы будете искать. Точные имена классов Shein меняются со временем, поэтому по возможности используйте частичные совпадения, например подстроку product-card, а не хрупкую полную цепочку классов.

Шаг 1: загрузка отрендеренной страницы листинга

Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его своим токеном, задайте URL листинга и запросите его с включённым рендерингом. Проверка кода статуса перед разбором позволяет обнаруживать сбои явно, а не молча.

python
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_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", "ignore")
    print(f"Request failed: {response['status_code']}")
    return None

if __name__ == "__main__":
    listing_url = "https://www.shein.com/Women-Clothing-c-2030.html"
    html = crawl(listing_url)
    print(html[:500] if html else "No HTML returned")

Два параметра ожидания важны для сетки, которая заполняется по мере загрузки страницы. ajax_wait указывает API дождаться завершения асинхронного контента, а page_wait задаёт фиксированную задержку в миллисекундах после загрузки, чтобы поздно рендеримые карточки успели появиться до захвата страницы. Запустите скрипт, и вы должны увидеть реальную разметку товаров, а не почти пустую оболочку. Это подтверждает, что рендеринг работает, ещё до написания единого селектора.

Crawlbase Crawling API

Сетка товаров появляется только после выполнения JavaScript страницы и только если Shein воспринимает запрос как запрос реального покупателя. Crawling API принимает ваш токен, запускает страницу листинга в реальном браузере, ротирует резидентские IP на стороне сервера, обрабатывает любой вызов и возвращает готовый HTML. Вам не нужно самостоятельно поддерживать флот headless-браузеров и пул прокси. Начните с бесплатного уровня до 20 000 запросов, указав URL категории или поиска.

Шаг 2: разбор карточек товаров с помощью BeautifulSoup

Получив отрендеренный HTML, загрузите его в BeautifulSoup, найдите все карточки товаров и извлеките каждое поле по его селектору. Shein оборачивает каждый товар в контейнер карточки, на который нужно ориентироваться при выборке, хранит название в ссылке-имени, показывает цену в элементе цены и раскрывает миниатюру и ссылку внутри карточки. Оберните каждую карточку в try/except, чтобы один повреждённый листинг не прерывал выполнение.

python
from bs4 import BeautifulSoup

BASE = "https://www.shein.com"

def text_of(card, selector):
    el = card.select_one(selector)
    return el.get_text(strip=True) if el else None

def absolute(href):
    if not href:
        return None
    if href.startswith("//"):
        return "https:" + href
    return href if href.startswith("http") else BASE + href

def parse_link(card):
    a = card.select_one("a[href]")
    return absolute(a["href"]) if a else None

def parse_image(card):
    img = card.select_one("img")
    if not img:
        return None
    src = img.get("src") or img.get("data-src")
    return absolute(src)

def scrape_listing(html):
    soup = BeautifulSoup(html, "html.parser")
    cards = soup.select("section[class*='product-card']")
    results = []
    for card in cards:
        try:
            title = text_of(card, "a.goods-title-link")
            if not title:
                continue
            results.append({
                "title": title,
                "price": text_of(card, "span.product-card__price"),
                "rating": text_of(card, "span.rate-num"),
                "link": parse_link(card),
                "image": parse_image(card),
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return results

Вспомогательная функция text_of находит один элемент внутри карточки и возвращает None при его отсутствии вместо того, чтобы выбрасывать исключение при вызове .get_text() на пустом объекте. Это делает извлечение устойчивым к отсутствующим полям, что распространено, поскольку не каждый товар показывает рейтинг. Вспомогательная функция absolute нормализует ссылки и источники изображений до полных URL, поскольку Shein часто возвращает протокол-относительный источник // или относительный href. Пропуск карточек без названия отсеивает пустые слоты-заглушки, которые Shein оставляет в сетке.

Selectors drift

Имена классов Shein (контейнер карточки, элемент цены, элемент рейтинга) меняются при обновлении сайта, тогда как структурные паттерны, такие как подстрока product-card и внутренний якорный тег, более устойчивы. Рассматривайте приведённые выше селекторы на основе классов как отправную точку, а не жёсткий контракт. Если поле возвращается как None для каждой карточки, заново изучите живую страницу листинга в инструментах разработчика браузера и обновите селектор. Периодическое обновление селекторов, норма для любого производственного парсера.

Шаг 3: сборка скрипта и экспорт в JSON и CSV

Теперь соедините загрузку и разбор в один рабочий скрипт, затем запишите записи как в JSON, так и в CSV, чтобы можно было загрузить их в ноутбук или таблицу. Загрузите отрендеренную страницу листинга, передайте её парсеру и выгрузите структурированные строки.

python
import csv
import json
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})
BASE = "https://www.shein.com"
FIELDS = ["title", "price", "rating", "link", "image"]

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", "ignore")
    print(f"Request failed: {response['status_code']}")
    return None

def text_of(card, selector):
    el = card.select_one(selector)
    return el.get_text(strip=True) if el else None

def absolute(href):
    if not href:
        return None
    if href.startswith("//"):
        return "https:" + href
    return href if href.startswith("http") else BASE + href

def parse_link(card):
    a = card.select_one("a[href]")
    return absolute(a["href"]) if a else None

def parse_image(card):
    img = card.select_one("img")
    if not img:
        return None
    src = img.get("src") or img.get("data-src")
    return absolute(src)

def scrape_listing(html):
    soup = BeautifulSoup(html, "html.parser")
    cards = soup.select("section[class*='product-card']")
    results = []
    for card in cards:
        try:
            title = text_of(card, "a.goods-title-link")
            if not title:
                continue
            results.append({
                "title": title,
                "price": text_of(card, "span.product-card__price"),
                "rating": text_of(card, "span.rate-num"),
                "link": parse_link(card),
                "image": parse_image(card),
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return results

def export(rows, name="shein_listing"):
    with open(f"{name}.json", "w", encoding="utf-8") as f:
        json.dump(rows, f, indent=2, ensure_ascii=False)
    with open(f"{name}.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDS)
        writer.writeheader()
        writer.writerows(rows)
    print(f"Saved {len(rows)} products to {name}.json and {name}.csv")

def main():
    url = "https://www.shein.com/Women-Clothing-c-2030.html"
    html = crawl(url)
    if not html:
        return
    rows = scrape_listing(html)
    export(rows)

if __name__ == "__main__":
    main()

Запустите полный скрипт командой python shein_listing.py. Он загружает отрендеренную страницу листинга, разбирает по одной строке на каждый товар и записывает как shein_listing.json, так и shein_listing.csv. Общий список FIELDS синхронизирует порядок столбцов CSV с ключами словаря, поэтому два экспорта никогда не расходятся.

Как выглядит результат

Вы получаете чистый список записей о товарах в порядке сетки, готовый к записи в JSON, CSV или базу данных.

json
[
  {
    "title": "Women's Ribbed Knit Long Sleeve Bodycon Dress",
    "price": "$12.49",
    "rating": "4.92",
    "link": "https://www.shein.com/Ribbed-Knit-Bodycon-Dress-p-12345678.html",
    "image": "https://img.ltwebstatic.com/images/ribbed-dress.jpg"
  },
  {
    "title": "Floral Print Tie Front Blouse",
    "price": "$9.00",
    "rating": "4.78",
    "link": "https://www.shein.com/Floral-Print-Blouse-p-87654321.html",
    "image": "https://img.ltwebstatic.com/images/floral-blouse.jpg"
  }
]

Масштабирование на несколько страниц и категорий

Одна страница, это демо; реальная исследовательская задача охватывает всю категорию. Shein пагинирует листинги с помощью параметра запроса ?page=, поэтому вы последовательно перебираете страницы до тех пор, пока очередная страница не вернётся пустой, а затем переходите к следующей категории. Темп запросов должен быть таким, чтобы не перегружать Shein в плотном цикле.

python
import time

CATEGORIES = {
    "women-clothing": "https://www.shein.com/Women-Clothing-c-2030.html",
    "dresses": "https://www.shein.com/Dresses-c-1727.html",
}

def scrape_categories(categories, max_pages=5):
    everything = {}
    for name, base_url in categories.items():
        rows = []
        for page in range(1, max_pages + 1):
            sep = "&" if "?" in base_url else "?"
            page_url = f"{base_url}{sep}page={page}"
            html = crawl(page_url)
            if not html:
                break
            found = scrape_listing(html)
            if not found:
                break
            rows.extend(found)
            print(f"{name} page {page}: {len(found)} products")
            time.sleep(2)
        everything[name] = rows
    return everything

Прерывание при пустых результатах останавливает вас досрочно, когда в категории заканчиваются товары, ограничение max_pages удерживает продолжительность прогона в рамках, а задержка time.sleep(2) между запросами задаёт темп, чтобы избежать быстрого трафика, характерного для скраперов. Использование имени категории в качестве ключа выходных данных сохраняет каждый список отдельно, что удобно при сравнении цен между категориями. Чтобы отслеживать изменения цен со временем, запускайте задачу по расписанию, отмечайте каждый экспорт датой и сравнивайте последовательные снимки. Это напрямую вписывается в рабочий процесс анализа цен, где собранные поля листинга становятся исходным сигналом.

Как оставаться незаблокированным

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

  • Соблюдайте темп запросов. Делайте задержки между страницами и категориями вместо того, чтобы парсить всё на максимальной скорости. Планируйте тяжёлые задачи на часы с меньшей нагрузкой, чтобы не перегружать серверы Shein.
  • Опирайтесь на ротацию. Пул резидентских IP-адресов распределяет запросы между множеством реальных пользовательских адресов, не давая ни одному из них превысить ограничение скорости. Crawling API делает это за вас; если вы строите собственный стек, именно на это стоит обратить внимание.
  • Сохраняйте только необходимое. Записывайте поля листинга, нужные для вашего проекта, и отбрасывайте остальное. Периодически проверяйте селекторы, чтобы парсер успевал за изменениями разметки.

Более широкое руководство по предотвращению блокировок см. в статье как парсить сайты, не попадая в блокировку, а о том, почему здесь важен рендеринг, читайте в материале как парсить JavaScript-сайты. Для общего контекста получения структурированных данных о товарах из интернет-магазинов наш обзор парсинга данных электронной коммерции охватывает паттерны, которым следует этот парсер.

Легально ли парсить Shein?

Допустимость парсинга Shein зависит от условий обслуживания Shein, вашей юрисдикции и целей использования данных. Условия Shein ограничивают автоматизированный доступ, поэтому парсинг может противоречить этим условиям независимо от того, насколько аккуратно настроен ваш инструментарий. Ни один из приведённых здесь кодов не меняет этого; он лишь реализует техническую часть. Ознакомьтесь с условиями обслуживания Shein и файлом robots.txt и рассматривайте оба документа как границы для того, что вы собираете. При коммерческом или конкурентном использовании правовая картина усложняется, и консультация с юристом по вашему конкретному случаю будет разумным шагом.

Несколько правил, которых стоит придерживаться. Собирайте только публичные данные: названия товаров, цены, рейтинги, ссылки в листингах и URL миниатюр, которые каждый может увидеть на странице листинга Shein без регистрации. Поддерживайте объём запросов достаточно низким, чтобы не перегружать серверы Shein, и избегайте персональных данных, в том числе любой информации, связанной с идентифицируемыми покупателями или рецензентами, помимо публично опубликованной. Не распространяйте фотографии товаров Shein как свои собственные: URL изображения, это ссылка, а не лицензия на публикацию медиа. Если вы планируете повторно использовать данные в коммерческих целях, получите разрешение или официальное соглашение, не считая молчание согласием.

Это руководство намеренно ограничено публичными страницами категорий и поиска, поскольку именно это делает работу защищённой. Оно не охватывает ничего за пределами публичного доступа, данных аккаунта или заказов, персональной информации или попыток обойти аутентификацию или вызов, на прохождение которого у вас нет прав. Если Shein предлагает партнёрскую программу, подходящую для вашего случая, это правильный инструмент при необходимости больших объёмов, гарантированной структуры или коммерческих прав. Если вашему проекту нужно больше, чем публичные данные листинга, официальный канал или соглашение о данных, это правильный путь, а не более хитрый парсер.

Итоги

Ключевые выводы

  • Листинги, это публичный сигнал о товарах. Каждая категория Shein и страница поиска отображают названия, цены, рейтинги и ссылки, именно поэтому они так полезны для мониторинга цен и исследования продукта.
  • Необходимы рендеринг и доверенный IP одновременно. Shein заполняет сетку товаров на стороне клиента и блокирует трафик ботов, поэтому Crawling API рендерит страницу за резидентским IP в одном вызове.
  • BeautifulSoup выполняет извлечение. Перебирайте контейнеры product-card и сопоставляйте название, цену, рейтинг, ссылку и изображение с текущими селекторами, ожидая их изменения.
  • Экспортируйте в JSON и CSV. Общий список полей синхронизирует оба файла, а пагинация с ?page= до пустой страницы масштабирует прогон на всю категорию.
  • Работайте только с публичными данными. Уважайте условия обслуживания и robots.txt Shein, не публикуйте изображения товаров повторно и никогда не касайтесь аккаунтов, заказов или персональной информации.

Часто задаваемые вопросы

Почему обычный запрос не возвращает товары с Shein?

Shein рендерит листинги на стороне клиента, поэтому обычный HTTP-запрос получает почти пустую оболочку без карточек товаров. Помимо этого, Shein блокирует трафик, не похожий на запросы реального браузера. Рендеринг страницы через Crawling API за доверенным IP решает обе проблемы, поэтому парсер здесь маршрутизирует запрос именно через него, а не получает URL напрямую.

Как парсить конкретную категорию или поиск на Shein?

Направьте парсер на URL категории, например /Women-Clothing-c-2030.html, или на URL поиска вида /pdsearch/dress/. Оба типа отображают одинаковую сетку карточек товаров, поэтому те же самые селекторы подходят для обоих. Чтобы охватить несколько категорий, ведите словарь имён и URL и перебирайте его, делая небольшие задержки между страницами.

Можно ли получить артикул, цвета и размеры для каждого товара?

Эти поля находятся на странице с подробным описанием каждого товара, а не в сетке листинга. Сначала соберите поле link из листинга, затем загрузите каждую страницу товара через ту же функцию crawl и разберите артикул, полное описание, цветовые варианты и размеры с этой страницы. Прежние поля соответствуют двухэтапному парсингу: листинг для обнаружения, страница товара для детализации.

Как обрабатывать пагинацию на Shein?

Shein пагинирует листинги с помощью параметра запроса ?page=. Перебирайте страницы по порядку, останавливайтесь, когда страница возвращает пустой результат, и ограничивайте цикл максимальным числом страниц, чтобы прогон оставался в рамках. Вспомогательная функция scrape_categories выше делает именно это, а задержка после каждого запроса не даёт прогону выглядеть как быстрый трафик.

Что лучше: экспортировать в JSON или CSV?

В оба формата, и скрипт записывает оба из одних и тех же записей. JSON сохраняет вложенную структуру и легко загружается обратно в Python, тогда как CSV открывается непосредственно в таблице для быстрой фильтрации и построения графиков. Общий список FIELDS сохраняет порядок столбцов CSV в соответствии с ключами словаря, поэтому два файла никогда не расходятся.

Как избежать блокировки при парсинге Shein?

Поддерживайте низкую частоту запросов с одного IP, добавляйте задержки между страницами и категориями, и маршрутизируйте через ротируемые резидентские IP, чтобы ни один адрес не превысил ограничение скорости. Crawling API управляет ротацией, доверенным пулом IP и обработкой вызовов за вас; если вы строите собственный стек, именно на это стоит потратить усилия. Следите за кодами статуса и снижайте темп, когда начнут поступать вызовы.

Начать создавать

Обходите любой сайт в масштабе, без борьбы с инфраструктурой.

Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

Самообслуживание · Звонок отдела продаж не требуется · Доступны корпоративные объёмы краулинга