Цена, это единственное поле на странице товара Walmart, которое меняется, тогда как всё остальное остаётся неизменным. Название, бренд, модель, они стабильны, но цифра рядом с кнопкой покупки меняется вслед за акциями, спросом и сезонными сдвигами. Если вы хотите отслеживать эти изменения, сравнивать цены по набору товаров или мониторить каталог конкурента, вам нужно снова и снова считывать одну и ту же цену и фиксировать каждое значение там, где его можно нанести на график.
Это руководство покажет, как парсить цены Walmart с помощью Python и превратить их в журнал наблюдений для анализа. Вы создадите небольшой работающий скрапер, который получает отрисованную страницу товара Walmart через Crawling API, извлекает название и цену из HTML с помощью BeautifulSoup и добавляет каждое значение в JSON и CSV с меткой времени, чтобы отслеживать динамику цен. Мы ограничим руководство публичными данными о товарах и листингах, а раздел о правовых аспектах в конце написан не для галочки, поэтому прочитайте его прежде, чем направить скрапер на реальные объёмы.
Что вы создадите
Скрипт на Python, который принимает URL товара Walmart, получает отрисованную страницу через Crawling API, извлекает структурированную запись и добавляет её в журнал цен с временными метками. В качестве рабочего примера мы используем листинг восстановленного iPhone и извлекаем с каждой страницы товара следующие поля:
- Title название товара, например "Restored Apple iPhone 13, Carrier Unlocked, 128GB Red".
- Price текущая цена, отображаемая рядом с кнопкой покупки.
- Discount сумма скидки в долларах, если листинг её показывает.
- Rating средняя оценка в звёздах, если у товара есть отзывы.
- Timestamp время в формате ISO, добавляемое в момент парсинга, чтобы каждое значение стало точкой на графике.
Почему обычный запрос не работает на Walmart
Если запросить URL товара Walmart через простой HTTP-клиент, вы получите ответ со статусом 200 и почти без данных о цене в теле ответа. Причин две. Во-первых, Walmart строит страницы товаров на стороне клиента: начальный HTML представляет собой оболочку, которая заполняет название, цену и рейтинг только после того, как JavaScript страницы выполнится в браузере. Во-вторых, Walmart быстро выявляет автоматизированный трафик. IP-адреса датацентров и паттерны запросов, не похожие на действия реального браузера, получают CAPTCHA или блокируются ещё до того, как будет отрисована цена.
Таким образом, работающий скрапер цен должен объединять в одном запросе: браузер, который реально рендерит страницу, и IP-адрес, который платформа воспринимает как адрес реального покупателя. Можно собрать это самостоятельно из безголового браузера и пула ротируемых жилых прокси, но их интеграция и поддержка занимает большую часть работы. Crawling API объединяет оба компонента в одном вызове: вы отправляете URL с токеном JavaScript, он рендерит страницу через доверенный жилой IP и возвращает готовый HTML для парсинга.
Crawlbase предлагает два типа токенов. Обычный токен получает статичный HTML; JavaScript (JS) токен сначала рендерит страницу в реальном браузере. Walmart загружает цену и рейтинг на стороне клиента, поэтому здесь нужен именно JS-токен. При использовании обычного токена вернётся та же пустая оболочка, что и при обычном запросе, и элемент с ценой в ней просто отсутствует.
Предварительные требования
Перед написанием кода нужно подготовить несколько вещей. Это не займёт много времени.
Базовые знания Python. Вы должны уметь писать и запускать скрипт на Python, а также устанавливать пакеты через pip. Если язык для вас новый, наше руководство по парсингу сайтов с Python охватывает основы, необходимые для этого туториала.
Python 3.8 или новее. Проверьте версию командой python --version. Если не установлен, скачайте с python.org или через дистрибутив вроде Anaconda.
Аккаунт Crawlbase и JS-токен. Зарегистрируйтесь, откройте дашборд и скопируйте JavaScript (JS) токен со страницы документации аккаунта. Бесплатный тариф включает 1000 запросов без привязки карты, чего вполне достаточно для создания и тестирования скрапера. Обращайтесь с токеном как с паролем: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.
Настройка проекта
Создайте виртуальное окружение, чтобы изолировать зависимости проекта, затем установите три библиотеки, которые понадобятся скраперу.
python --version python -m venv walmart_env source walmart_env/bin/activate pip install crawlbase beautifulsoup4 pandas
В Windows активируйте окружение командой walmart_env\Scripts\activate вместо строки с source. Три зависимости выполняют основную работу: crawlbase, официальный клиент для Crawling API, beautifulsoup4 парсит возвращаемый HTML, позволяя извлекать каждое поле по CSS-селектору, а pandas обеспечивает экспорт в CSV в конце, чтобы история цен открывалась в любой таблице.
Изучение страницы товара Walmart
Страница товара Walmart содержит много информации на одном экране: название, карусель изображений, блок цены, звёздный рейтинг с количеством отзывов, описание и данные продавца. Для отслеживания цен важны лишь некоторые из них. Нужные поля: название (чтобы знать, к какому товару относится запись), текущая цена, сумма скидки (если она указана) и рейтинг.
Перед написанием селекторов откройте страницу товара в браузере, кликните правой кнопкой по цене и выберите «Просмотр кода». Вы увидите, что цена представлена атрибутом itemprop="price" внутри контейнера price-wrap, название, в элементе h1#main-title, а скидка и рейтинг скрыты за маркерами data-testid. Именно эти атрибуты и являются целями. Имена утилитарных классов Walmart часто меняются, а семантические атрибуты более устойчивы, поэтому по возможности опирайтесь на них.
Шаг 1: Получение отрисованной страницы товара
Начните с получения готовой страницы. Импортируйте класс CrawlingAPI, инициализируйте его с JS-токеном и запросите URL товара. Проверка кода статуса перед парсингом позволяет обнаруживать ошибки явно, а не скрыто.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) def crawl(product_url): options = {"ajax_wait": "true", "page_wait": 3000} response = api.get(product_url, options) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None if __name__ == "__main__": url = "https://www.walmart.com/ip/Restored-Apple-iPhone-13-Carrier-Unlocked-128-GB-Red-Refurbished/462799546" html = crawl(url) print(html[:500] if html else "No HTML returned")
Два параметра ожидания важны для цели с клиентским рендерингом. ajax_wait указывает API дождаться завершения загрузки асинхронного контента, а page_wait выдерживает фиксированное число миллисекунд после загрузки, чтобы блок с ценой появился до захвата страницы. Трёх секунд достаточно для начала; увеличьте, если цена не возвращается. Тело декодируется как latin1, поскольку страницы Walmart могут содержать символы, на которых строгое декодирование UTF-8 даст сбой. Запустите скрипт, и вы должны увидеть реальную разметку товара, а не пустую оболочку, которую вернёт обычный запрос. Это подтверждает, что рендеринг работает, ещё до написания единого селектора.
Блок с ценой существует только после того, как Walmart рендерит страницу за доверенным IP, именно на это опирается функция crawl. Crawling API принимает JS-токен, запускает страницу в реальном браузере, ротирует жилые IP на стороне сервера и возвращает готовый HTML, так что вам не нужно управлять парком безголовых браузеров и пулом прокси самостоятельно. Начните с одного URL товара на бесплатном тарифе.
Шаг 2: Извлечение названия и цены с помощью BeautifulSoup
Получив отрисованный HTML, загрузите его в BeautifulSoup и извлеките каждое поле по его селектору. Цена находится в span с атрибутом itemprop="price" внутри контейнера price-wrap, название, в h1#main-title, скидка и рейтинг, за маркерами data-testid. Небольшой вспомогательный метод возвращает пустую строку, если элемент отсутствует, чтобы отсутствие одного поля не прерывало выполнение.
from bs4 import BeautifulSoup from datetime import datetime, timezone def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else "" def parse_product(html): soup = BeautifulSoup(html, "html.parser") return { "title": text_of(soup, "h1#main-title"), "price": text_of(soup, 'span[data-testid="price-wrap"] span[itemprop="price"]'), "discount": text_of(soup, 'div[data-testid="dollar-saving"] span:last-child'), "rating": text_of(soup, 'div[data-testid="reviews-and-ratings"] span.rating-number'), "scraped_at": datetime.now(timezone.utc).isoformat(), }
Вспомогательный метод text_of выполняет запрос к одному элементу и возвращает пустую строку, если тот отсутствует, вместо того чтобы выбрасывать исключение при вызове .get_text() для несуществующего объекта. Это делает извлечение устойчивым при отсутствии полей, что часто встречается, поскольку не каждый листинг содержит скидку или рейтинг. Цена берётся из span с атрибутом itemprop="price", канонического места, где Walmart размечает текущую цену, а scraped_at снабжает каждую запись временем её создания. Именно эта метка времени превращает разовый парсинг в ряд цен, который можно построить на графике позднее.
Имена утилитарных классов Walmart меняются без предупреждения, а значения data-testid в блоках цены и скидки тоже периодически обновляются. Воспринимайте приведённые выше селекторы как отправную точку, а не как неизменный контракт. Если цена возвращается пустой на странице, где она точно есть, заново проверьте живую страницу через инструменты разработчика браузера и обновите селектор. Периодическое обновление селекторов, нормальная практика для любого производственного скрапера, а не признак поломки.
Шаг 3: Добавление каждого значения в журнал цен
Теперь объедините получение и парсинг в единый исполняемый скрипт и добавляйте каждое значение в JSON-файл и CSV. Именно добавление, а не перезапись, составляет суть: каждый запуск добавляет одну датированную строку на товар, и через дни или недели эти строки формируют историю цен, которую можно визуализировать.
import json import os import pandas as pd from bs4 import BeautifulSoup from datetime import datetime, timezone from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) PRODUCTS = [ "https://www.walmart.com/ip/Restored-Apple-iPhone-13-Carrier-Unlocked-128-GB-Red-Refurbished/462799546", ] def crawl(product_url): options = {"ajax_wait": "true", "page_wait": 3000} response = api.get(product_url, options) if response["status_code"] == 200: return response["body"].decode("latin1") 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 "" def parse_product(html, url): soup = BeautifulSoup(html, "html.parser") return { "title": text_of(soup, "h1#main-title"), "price": text_of(soup, 'span[data-testid="price-wrap"] span[itemprop="price"]'), "discount": text_of(soup, 'div[data-testid="dollar-saving"] span:last-child'), "rating": text_of(soup, 'div[data-testid="reviews-and-ratings"] span.rating-number'), "url": url, "scraped_at": datetime.now(timezone.utc).isoformat(), } def append_json(record, path="walmart_prices.json"): history = [] if os.path.exists(path): with open(path) as f: history = json.load(f) history.append(record) with open(path, "w") as f: json.dump(history, f, indent=2) return history def main(): for url in PRODUCTS: html = crawl(url) if not html: continue record = parse_product(html, url) append_json(record) print(json.dumps(record, indent=2)) history = json.load(open("walmart_prices.json")) pd.DataFrame(history).to_csv("walmart_prices.csv", index=False) if __name__ == "__main__": main()
Функция append_json считывает существующую историю, добавляет новую запись и записывает весь список обратно, так что JSON-файл увеличивается на одну запись с каждым запуском. По завершении цикла скрипт с помощью pandas перестраивает walmart_prices.csv из этой истории, создавая плоскую таблицу, которую можно открыть в любой таблице для построения графика. Добавьте URL в список PRODUCTS, и тот же код будет отслеживать несколько товаров одновременно. Чтобы собирать данные с течением времени, настройте запуск этого скрипта через cron-задачу раз в день, и каждый запуск будет добавлять новую датированную строку на товар.
Как выглядят результаты
Запустите полный скрипт командой python scraper.py, и каждое значение будет напечатано в формате JSON и занесено в журнал цен. Через несколько запусков на протяжении пары дней JSON-файл будет содержать небольшую серию данных по каждому товару.
[ { "title": "Restored Apple iPhone 13, Carrier Unlocked, 128 GB Red (Refurbished)", "price": "$449.00", "discount": "$200.00", "rating": "(4.4)", "url": "https://www.walmart.com/ip/...462799546", "scraped_at": "2026-06-09T14:05:33+00:00" }, { "title": "Restored Apple iPhone 13, Carrier Unlocked, 128 GB Red (Refurbished)", "price": "$429.00", "discount": "$220.00", "rating": "(4.4)", "url": "https://www.walmart.com/ip/...462799546", "scraped_at": "2026-06-10T14:04:11+00:00" } ]
Два записи имеют одинаковые название и URL, но отличаются ценой и датой, именно такая структура нужна для отслеживания цен. Загрузив walmart_prices.csv в pandas, можно вычислить минимальную, максимальную и среднюю цену по каждому товару, отметить снижение ниже порогового значения или построить ряд данных. Если вы хотите превратить этот журнал в сравнительный вид по нескольким магазинам, сопутствующее руководство по созданию инструмента сравнения цен продолжает с того места, где заканчивается это.
Парсинг цен по большому числу товаров
Отслеживание одного листинга, это демо; реальная задача предполагает мониторинг набора товаров, и зачастую URLs у вас нет заранее. Чтобы сформировать такой набор, сначала парсят страницу результатов поиска, собирают ссылки на товары, а затем запускают скрапер цен для каждой из них. Извлечение этих ссылок со страницы поиска Walmart, отдельная задача, детально разобранная в нашем руководстве по парсингу страниц поиска Walmart с Python. Получив URLs, добавьте их в список PRODUCTS, и цикл прочитает цену каждого.
Делайте паузы в цикле, чтобы не нагружать Walmart пачкой запросов подряд. Небольшая задержка между запросами к разным товарам снижает частоту запросов и поддерживает стабильность работы, такой же подход оправдывает себя с любым коммерческим ресурсом с защитой.
import time def track_prices(urls): readings = [] for url in urls: html = crawl(url) if not html: continue record = parse_product(html, url) append_json(record) readings.append(record) print(f"{record['title'][:40]}: {record['price']}") time.sleep(2) return readings
time.sleep(2) между товарами, это минимальная задержка, а не максимальная: увеличьте её для больших наборов. Поскольку append_json делает запись после каждого товара, запуск, прерванный в середине, сохраняет уже собранные данные, и вы не потеряете результаты длинной задачи из-за одной неудачной страницы.
Как избежать блокировки
Даже при отрисовке страниц Walmart следит за трафиком, характерным для скраперов. Несколько привычек поддерживают стабильность работы и применимы к любому коммерческому ресурсу с защитой.
- Регулируйте запросы. Распределяйте запросы с задержкой между товарами и не повторяйте парсинг одного листинга чаще, чем необходимо. Для отслеживания цен одного-двух раз в день обычно достаточно, чтобы фиксировать все существенные изменения.
- Используйте ротацию. Пул жилых IP распределяет запросы по множеству реальных адресов, чтобы ни один из них не превышал лимит запросов. Crawling API делает это за вас; если вы собираете собственный стек, это ключевой компонент, который нужно реализовать правильно.
- Следите за кодами статуса. Если запуск начинает возвращать ошибки или запросы на верификацию, это сигнал о том, что текущая частота или уровень IP недостаточны. Воспринимайте это как призыв снизить нагрузку, а не как шум, который можно игнорировать.
Полное руководство по этой теме смотрите в нашем материале о том, как парсить сайты без блокировок. Если вы хотите парсить один листинг детально, включая данные о вариантах и характеристиках, сопутствующее руководство по парсингу страницы товара Walmart с Selenium выходит за рамки одной только цены, а более широкий аргумент в пользу отслеживания цен конкурентов изложен в статье об использовании веб-парсинга для ценовой аналитики.
Законен ли парсинг Walmart?
Допустимость парсинга Walmart зависит от условий использования сервиса, вашей юрисдикции и того, как вы применяете данные. Условия Walmart ограничивают автоматизированный доступ, поэтому парсинг может нарушать их независимо от того, насколько аккуратно реализован ваш инструментарий. Ни один из приведённых здесь кодов это не меняет; он лишь делает техническую часть рабочей. Ознакомьтесь с Условиями использования Walmart и его файлом robots.txt и рассматривайте оба документа как границу того, что вы собираете.
Несколько правил, которых стоит придерживаться. Собирайте только публичные данные: названия товаров, цены, скидки и рейтинги, которые любой желающий видит на странице товара или в результатах поиска без аккаунта. Соблюдайте ожидания Walmart в отношении частоты запросов и держите их объём на уровне, при котором вы не нагружаете серверы, что несложно при отслеживании цен, одного обращения в день на товар вполне достаточно. Не трогайте персональные данные, в том числе любую информацию, связанную с идентифицируемыми покупателями, рецензентами или продавцами сверх того, что публично указано. Если вы планируете коммерческое использование цен, получите разрешение или официальное соглашение, а не рассчитывайте на то, что молчание равнозначно согласию.
Это руководство намеренно ограничено публичными страницами товаров и листингов, поскольку именно такая область делает работу защищённой. Здесь не рассматривается ничего, что находится за авторизацией, данных аккаунта или заказов, персональных данных, платёжных и оформительских потоков, а также любых попыток обойти аутентификацию. Для лицензированного или массового доступа Walmart предлагает официальные API и партнёрские программы, и это правильный инструмент, когда вам нужны большие объёмы, гарантированная структура или коммерческие права. Если вашему проекту нужно больше, чем публичные цены, официальный API или соглашение о данных, правильный путь, а не более изощрённый скрапер.
Ключевые выводы
- Цены Walmart рендерятся на стороне клиента. Обычный запрос возвращает пустую оболочку, поэтому перед тем как элемент с ценой появится для парсинга, необходимо отрисовать страницу с помощью JS-токена.
-
Используйте устойчивые атрибуты. Берите цену из span с
itemprop="price", а название изh1#main-title; ожидайте, что окружающие имена классов будут меняться, и заново проверяйте страницу, когда поле возвращается пустым. -
Временная метка превращает парсинг в ряд данных. Снабжайте каждую запись полем
scraped_atи добавляйте их вместо перезаписи, и ваши JSON и CSV станут историей цен, которую можно построить на графике. - Масштабируйте от поиска до корзины. Собирайте URLs товаров со страницы поиска, передавайте их в цикл, добавляйте задержку между запросами и запускайте по ежедневному расписанию для отслеживания со временем.
- Оставайтесь в рамках публичных данных. Соблюдайте Условия использования Walmart и robots.txt, предпочитайте официальный API Walmart для лицензированных или массовых данных и никогда не трогайте аккаунты, заказы или персональные данные.
Часто задаваемые вопросы
Почему обычный запрос не возвращает цену с Walmart?
Потому что Walmart загружает цену на страницу на стороне клиента с помощью JavaScript. Начальный HTML представляет собой оболочку, и элемент с ценой появляется только после выполнения скриптов страницы в браузере, поэтому прямой HTTP-запрос возвращает статус 200 с пустой ценой. Чтобы её прочитать, нужно сначала отрисовать страницу, именно это и делает JS-токен Crawling API.
Как отслеживать цену Walmart с течением времени?
Запускайте скрапер по расписанию, раз или два в день, и добавляйте каждое значение в один и тот же JSON и CSV файл с меткой времени. Вспомогательный метод append_json из этого руководства добавляет одну датированную запись за запуск вместо перезаписи, так что файл становится рядом цен. Загрузите этот CSV в pandas для вычисления минимума, максимума и среднего или для обнаружения снижения ниже порогового значения.
Можно ли одновременно парсить цены многих товаров?
Да. Добавьте каждый URL товара в список PRODUCTS или передайте список URLs в функцию track_prices, и цикл прочитает цену каждого. Если URLs у вас нет заранее, сначала спарсите страницу поиска Walmart для сбора ссылок на товары, а затем передайте их в цикл. Делайте небольшие паузы между запросами для регулирования нагрузки.
Мой селектор цены возвращает пустую строку. Что изменилось?
Почти наверняка это разметка Walmart. Имена утилитарных классов меняются без предупреждения, а значения data-testid рядом с блоками цены и скидки тоже периодически обновляются. Заново проверьте живую страницу товара через инструменты разработчика браузера, используйте более устойчивые цели itemprop="price" и h1#main-title там, где возможно, и обновите селекторы. Периодическое обслуживание, нормальная практика для любого производственного скрапера.
Хранить ли цены в CSV, JSON или базе данных?
Для нескольких товаров, отслеживаемых несколько недель, JSON и CSV из этого руководства вполне достаточны и открываются где угодно. По мере роста истории или при отслеживании сотен товаров переходите на базу данных, например SQLite или PostgreSQL, чтобы запрашивать данные по диапазону дат и товару без загрузки всего файла. Структура записи остаётся прежней; меняется только уровень хранения.
Как избежать блокировки при парсинге цен Walmart?
Держите низкую частоту запросов с каждого IP, добавляйте задержку между товарами, не парсите один листинг чаще, чем необходимо, и маршрутизируйте трафик через ротируемые жилые IP, чтобы ни один адрес не превышал лимит. Crawling API управляет ротацией и доверенным пулом IP за вас; если вы строите собственный стек, именно в это стоит инвестировать. Следите за кодами статуса и снижайте нагрузку, как только начинаете получать запросы на верификацию.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
