Каталог Walmart является одним из богатейших публичных источников розничных данных в интернете: каждый поисковый запрос возвращает сетку списков товаров с названиями, ценами, звёздными рейтингами, количеством отзывов и ссылками на каждую страницу товара. Эти данные используются для отслеживания цен конкурентов, рыночных исследований, анализа ассортимента и мониторинга трендов. Проблема в том, что Walmart рендерит эти списки в браузере и активно защищается от автоматизированного трафика, поэтому обычный HTTP-запрос выдаёт вам JavaScript-оболочку вместо интересующих вас товаров.

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

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

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

  • Name название товара, например "Apple iPhone 15, 128GB, Black".
  • Price указанная цена на карточке.
  • Rating средний звёздный рейтинг, когда он есть у товара.
  • Reviews количество отзывов покупателей за этим рейтингом.
  • Link URL на собственную страницу товара.

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

Если вы запрашиваете URL поиска Walmart с помощью обычного HTTP-клиента, вы получаете ответ со статусом 200 и почти без данных о товарах в теле. Против вас работают два фактора. Во-первых, Walmart строит свою сетку результатов поиска на стороне клиента: исходный HTML является оболочкой, которая заполняется только после того, как JavaScript страницы выполняется в браузере. Во-вторых, Walmart быстро помечает автоматизированный трафик. IP-адреса датацентров и паттерны запросов, не похожие на реальный браузер, получают CAPTCHA или блокируются ещё до того, как попадут к отрендеренным листингам.

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

Why the JS token

Crawlbase предлагает два типа токенов. Обычный токен получает статический HTML; JavaScript (JS) токен сначала рендерит страницу в реальном браузере. Сетка результатов поиска Walmart рендерится на стороне клиента, поэтому здесь вам нужен JS-токен. Использование обычного токена возвращает ту же пустую оболочку, что и обычный запрос, и из неё нечего парсить.

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

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

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

Python 3.8 или выше. Проверьте свою версию командой python --version. Если у вас её нет, установите с python.org или через дистрибутив, такой как Anaconda.

Аккаунт Crawlbase и JS-токен. Зарегистрируйтесь, откройте панель управления и скопируйте JavaScript (JS) токен со страницы документации аккаунта. Обращайтесь с токеном как с паролем: он аутентифицирует ваши запросы, поэтому держите его вне системы контроля версий.

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

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

bash
python --version

python -m venv walmart_env
source walmart_env/bin/activate

pip install crawlbase beautifulsoup4

В Windows активируйте среду командой walmart_env\Scripts\activate вместо строки с source. Две зависимости выполняют основную работу: crawlbase является официальным клиентом для Crawling API, а beautifulsoup4 парсит возвращённый HTML, чтобы вы могли извлечь каждое поле из сетки результатов по CSS-селектору.

Структура страницы результатов поиска Walmart

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

Прежде чем писать селекторы, откройте страницу результатов поиска в браузере, щёлкните правой кнопкой мыши на карточке товара и выберите «Inspect». Вы увидите, что каждая карточка обёрнута в контейнер со стабильными атрибутами данных, а название, цена и рейтинг раскрываются через маркеры data-automation-id. Именно эти атрибуты вы и целитесь. Имена служебных классов Walmart меняются часто, но automation ID более долговечны, поэтому по возможности опирайтесь на них.

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

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

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

if __name__ == "__main__":
    query = "iPhone"
    search_url = f"https://www.walmart.com/search?q={query}"
    html = crawl(search_url)
    print(html[:500] if html else "No HTML returned")

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

Crawlbase Walmart Scraper

Walmart требует отрендеренной страницы за доверенным IP в одном вызове. Crawling API принимает JS-токен, запускает страницу в реальном браузере, ротирует жилые IP на стороне сервера и передаёт готовый HTML, так что вам не нужно самостоятельно запускать безголовый флот и пул прокси. Сначала направьте его на поисковый запрос на бесплатном тарифе.

Шаг 2: Парсинг сетки результатов с помощью BeautifulSoup

Имея отрендеренный HTML, загрузите его в BeautifulSoup, найдите каждую карточку товара и извлеките каждое поле по его селектору. Walmart оборачивает каждый листинг в контейнер, который вы можете выбрать, и раскрывает название и цену через атрибуты data-automation-id. Читайте ссылку из якоря карточки и парсите объединённую строку с рейтингом и количеством отзывов на два значения. Оборачивайте каждую карточку в try/except, чтобы один некорректный листинг не прерывал весь запуск.

python
from bs4 import BeautifulSoup

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

def parse_rating(card):
    el = card.select_one("span.w_iUH7")
    if not el:
        return None, None
    text = el.get_text(strip=True)
    rating = text.split(" out of")[0] if "out of" in text else None
    reviews = None
    if "reviews" in text:
        reviews = text.split("Stars.")[-1].replace("reviews", "").strip()
    return rating, reviews

def scrape_results(html):
    soup = BeautifulSoup(html, "html.parser")
    cards = soup.select("div[data-item-id]")
    results = []
    for card in cards:
        try:
            rating, reviews = parse_rating(card)
            link = card.select_one("a[href]")
            results.append({
                "name": text_of(card, 'span[data-automation-id="product-title"]'),
                "price": text_of(card, 'div[data-automation-id="product-price"] span.f2'),
                "rating": rating,
                "reviews": reviews,
                "link": link["href"] if link else None,
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return results

Вспомогательный метод text_of запрашивает один элемент внутри одной карточки и возвращает None, когда элемент отсутствует, вместо того чтобы генерировать исключение при вызове .get_text() от ничего. Это делает извлечение устойчивым к отсутствию поля, что часто случается, поскольку не каждый листинг имеет рейтинг. Цена читается из целочисленного span внутри ценового блока, а ссылка на товар берётся из href якоря карточки, а не его текста. Вспомогательный метод parse_rating разбивает объединённую строку Walmart "4.2 out of 5 Stars. 3244 reviews" на числовой рейтинг и количество отзывов, чтобы они хранились как отдельные поля.

Selectors drift

Служебные имена классов Walmart (ценовой span span.f2, строка рейтинга span.w_iUH7) меняются без предупреждения, а атрибуты контейнера карточки результатов иногда тоже смещаются. Воспринимайте приведённые выше селекторы как начальный шаблон, а не как контракт. Когда поле возвращает None для каждой карточки, повторно проверьте живую страницу результатов поиска с помощью инструментов разработчика в браузере и обновите селектор. Периодическое обслуживание селекторов нормально для любого производственного скрапера, это не признак поломки.

Шаг 3: Объединение всего вместе

Теперь соедините получение данных и парсинг в один работающий скрипт. Получите отрендеренную страницу результатов поиска, передайте её парсеру и выведите структурированные записи.

python
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("latin1")
    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 parse_rating(card):
    el = card.select_one("span.w_iUH7")
    if not el:
        return None, None
    text = el.get_text(strip=True)
    rating = text.split(" out of")[0] if "out of" in text else None
    reviews = None
    if "reviews" in text:
        reviews = text.split("Stars.")[-1].replace("reviews", "").strip()
    return rating, reviews

def scrape_results(html):
    soup = BeautifulSoup(html, "html.parser")
    cards = soup.select("div[data-item-id]")
    results = []
    for card in cards:
        try:
            rating, reviews = parse_rating(card)
            link = card.select_one("a[href]")
            results.append({
                "name": text_of(card, 'span[data-automation-id="product-title"]'),
                "price": text_of(card, 'div[data-automation-id="product-price"] span.f2'),
                "rating": rating,
                "reviews": reviews,
                "link": link["href"] if link else None,
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return results

def main():
    query = "iPhone"
    search_url = f"https://www.walmart.com/search?q={query}"
    html = crawl(search_url)
    if not html:
        return
    data = scrape_results(html)
    print(json.dumps(data, indent=2))

if __name__ == "__main__":
    main()

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

Запустите полный скрипт командой python scraper.py и получите чистый список записей, по одной на результат, готовый для записи в JSON, CSV или базу данных.

json
[
  {
    "name": "AT&T Apple iPhone 11, 64GB, Black - Prepaid Smartphone",
    "price": "399",
    "rating": "3.8",
    "reviews": "202",
    "link": "https://www.walmart.com/ip/..."
  },
  {
    "name": "Straight Talk Apple iPhone 11, 64GB, Black",
    "price": "249",
    "rating": "4.2",
    "reviews": "3244",
    "link": "https://www.walmart.com/ip/..."
  }
]

Обработка пагинации по страницам результатов

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

python
import time

def scrape_all_pages(query, max_pages=5):
    base = f"https://www.walmart.com/search?q={query}"
    all_results = []
    for page in range(1, max_pages + 1):
        page_url = f"{base}&page={page}"
        html = crawl(page_url)
        if not html:
            break
        results = scrape_results(html)
        if not results:
            break
        all_results.extend(results)
        print(f"Page {page}: {len(results)} products")
        time.sleep(2)
    return all_results

Ограничение max_pages удерживает запуск в разумных пределах, чтобы широкий запрос не крутился бесконечно, а прерывание по пустым результатам останавливает вас досрочно, когда Walmart заканчивает страницы. Вставка time.sleep(2) между страницами регулирует темп запросов, чтобы не обращаться к поиску в тесном цикле, что является самым быстрым способом получить ограничение. Настройте оба параметра в соответствии с вашим объёмом и ограничениями скорости ниже.

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

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

  • Регулируйте темп запросов. Распределяйте запросы с задержкой между страницами и варьируйте запросы, вместо того чтобы обходить один термин на полной скорости. time.sleep в цикле пагинации, это нижний предел, а не потолок.
  • Используйте ротацию. Пул жилых IP-адресов распределяет запросы по множеству реальных пользовательских адресов, чтобы ни один не превысил ограничение скорости. Crawling API берёт это на себя; если вы используете собственную инфраструктуру, именно эту часть нужно настроить правильно.
  • Читайте коды статусов. Запуск, который начинает возвращать запросы или ошибки, говорит вам, что текущей скорости или уровня IP уже недостаточно. Воспринимайте это как сигнал снизить нагрузку, а не шум, который нужно игнорировать.

Для получения более широкого руководства смотрите статью о том, как обходить CAPTCHA при веб-скрапинге, а если вы хотите глубоко скрапить отдельный листинг после сбора поисковых ссылок, сопутствующее руководство по скрапингу страницы товара Walmart с помощью Selenium продолжает именно с этого места. Для сравнения показателей управляемого API и обычного пула прокси на этой конкретной цели стоит прочитать бенчмарк прокси для скрапинга Walmart. Если вы предпочитаете направлять собственный трафик через ротируемый пул, а не через управляемый API, Smart AI Proxy (также называемый AI Proxy) предоставляет ту же ротацию жилых IP как подключаемую прокси-точку.

Законно ли скрапить Walmart?

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

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

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

Итоги

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

  • Поиск Walmart рендерится на стороне клиента. Обычный запрос возвращает пустую оболочку, поэтому необходимо отрендерить страницу перед её парсингом.
  • Нужны одновременно рендеринг и доверенный IP. Crawling API с JS-токеном делает оба шага в одном вызове; ajax_wait и page_wait контролируют, как долго ждать сетки.
  • BeautifulSoup выполняет извлечение. Пройдитесь по карточкам результатов и сопоставьте название, цену, рейтинг, отзывы и ссылку с текущими селекторами, ожидая их дрейфа.
  • Пагинируйте с помощью параметра page. Обходите &page= до тех пор, пока страница не вернёт пустые карточки, регулируйте темп запросов с задержкой и ограничивайте количество страниц.
  • Оставайтесь в рамках публичных данных. Соблюдайте ToS и robots.txt Walmart, предпочитайте официальный API Walmart для лицензированных или объёмных данных и никогда не трогайте аккаунты, заказы или персональную информацию.

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

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

Потому что Walmart строит свою сетку результатов поиска на стороне клиента с помощью JavaScript. Исходный HTML является оболочкой, которая заполняется только после того, как скрипты страницы выполняются в браузере, поэтому обычный HTTP-запрос возвращает статус 200 с пустыми листингами. Чтобы получить реальные данные, нужно сначала отрендерить страницу, именно это делает для вас JS-токен Crawling API.

Какой токен нужен для Walmart: обычный или JS?

JS-токен. Обычный токен получает статический HTML, который на Walmart является той же пустой оболочкой, что и обычный запрос. JS-токен рендерит страницу в реальном браузере перед возвратом HTML, чтобы карточки товаров присутствовали при парсинге BeautifulSoup.

Как скрапить все страницы поиска Walmart?

Walmart пагинирует с помощью параметра &page= в URL поиска. Увеличивайте его в цикле, скрапьте каждую страницу с тем же парсером и останавливайтесь, когда страница не возвращает карточек. Ограничивайте количество страниц и добавляйте короткую задержку между запросами, чтобы регулировать темп и не попасть под ограничение.

Мои селекторы возвращают None. Что изменилось?

Почти наверняка разметка Walmart. Служебные имена классов, такие как span.f2 для цены и span.w_iUH7 для строки рейтинга, меняются без предупреждения, а атрибуты контейнера карточки иногда тоже смещаются. Повторно проверьте живую страницу результатов поиска с помощью инструментов разработчика в браузере, по возможности отдавайте предпочтение более долговечным маркерам data-automation-id и обновляйте селекторы. Периодическое обслуживание нормально для любого производственного скрапера.

Можно ли скрапить данные о заказах, аккаунтах или оформлении заказов с Walmart?

Нет, и это руководство не охватывает данную тему. История заказов, данные аккаунтов и кассовые потоки находятся за логином, поэтому не являются публичными данными. Скрапинг контента, защищённого логином, или его обход выходят за рамки этого руководства и противоречат условиям Walmart. Для санкционированного доступа к более богатым данным верным путём является официальный API Walmart или партнёрское соглашение.

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

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

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

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

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

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