Walmart zmienia ceny niektórych produktów kilka razy dziennie. Jeśli kiedykolwiek próbowałeś śledzić to programowo, znasz ten ból: skrypt działa 20 minut, a potem po cichu zaczyna zwracać strony CAPTCHA udające zwykłe odpowiedzi 200 OK.
Spędziłem sporo czasu, obchodząc zabezpieczenia anty-botowe Walmartu w ramach naszej pracy nad pozyskiwaniem danych w Thunderbit i chcę podzielić się wszystkim, czego się nauczyłem — metodami, które naprawdę działają w 2025 roku, cichymi błędami zatruwającymi dane oraz uczciwym porównaniem między napisaniem własnego scrapera, płaceniem za scraping API a po prostu użyciem narzędzia no-code. Ten przewodnik obejmuje trzy metody ekstrakcji (parsowanie HTML, JSON z __NEXT_DATA__ oraz przechwytywanie wewnętrznego API), gotową do produkcji obsługę błędów, którą większość poradników całkowicie pomija, oraz szczery framework decyzyjny, który pomoże wybrać właściwe podejście. Znajdziesz tu coś dla siebie, niezależnie od tego, czy piszesz w Pythonie, czy po prostu chcesz mieć arkusz pełen cen do obiadu.
Dlaczego warto scrapować Walmart w Pythonie?
Walmart jest największym detalistą na świecie pod względem przychodów — 680,985 miliarda dolarów w roku fiskalnym 2025 — i od 12 kolejnych lat zajmuje 1. miejsce na Fortune Global 500. Serwis ma około 420 milionów aktywnych ofert, a dyrektor finansowy Walmartu wspominał o „pół miliarda SKU” na marketplace. Około 95% tych ofert pochodzi od sprzedawców zewnętrznych, co oznacza, że katalog jest bardzo zmienny — sprzedawcy rotują, warianty się zmieniają, a stany magazynowe przeskakują z dnia na dzień.

Ta zmienność właśnie dlatego sprawia, że scraping ma sens. Raport kwartalny nie uchwyci tego, co codzienny scraping. Oto najczęstsze zastosowania, które widzę:
| Zastosowanie | Kto tego potrzebuje | Co wyciągają |
|---|---|---|
| Monitorowanie cen konkurencji | Operacje e-commerce, narzędzia do repricingu | Ceny, promocje, zgodność z MAP |
| Wzbogacanie katalogu produktów | Zespoły sprzedaży i merchandisingu | Opisy, obrazy, specyfikacje, warianty |
| Śledzenie dostępności towaru | Łańcuch dostaw, dropshipperzy | Status magazynowy, informacje o sprzedawcy |
| Badania rynku i analiza trendów | Marketing, product managerowie | Oceny, recenzje, asortyment kategorii |
| Generowanie leadów | Zespoły sprzedaży | Nazwy sprzedawców, liczba produktów, kategorie |
Sam rynek oprogramowania do monitorowania cen konkurencji osiągnął 1,92 miliarda dolarów w 2025 roku i według prognoz ma wzrosnąć do 5,09 miliarda dolarów do 2033 roku. Zachowania konsumentów napędzają wydatki: 94% klientów porównuje ceny podczas zakupów online, a 83% porównuje oferty na wielu stronach.
Python jest domyślnym językiem do takich zadań. Raport Apify Infrastructure Report 2026 wskazuje, że Python odpowiada za 71,7% całego web scrapingu, a podstawowa biblioteka (requests) pobiera około 30 milionów pobrań tygodniowo. Jeśli scrapujesz na jakąkolwiek skalę, niemal na pewno robisz to w Pythonie.
Dlaczego Walmart jest jednym z najtrudniejszych serwisów do scrapowania
Walmart jest trudny właśnie dlatego, że działa na dwóch komercyjnych produktach anty-botowych po kolei: Akamai Bot Manager jako warstwa brzegowego WAF i TLS fingerprintingu oraz PerimeterX (przemianowany na HUMAN Security) jako warstwa behawioralnych wyzwań JavaScript. Scrape.do określa to połączenie jako „rzadkie i wyjątkowo trudne do obejścia”.

ScrapeOps ocenia Walmart na 9/10 pod względem ogólnej trudności scrapowania, a sam Akamai ma ocenę 9/10. Z mojego doświadczenia to całkiem trafne.
Z czym tak naprawdę musisz się zmierzyć:
Akamai Bot Manager analizuje fingerprint TLS (hash JA3/JA4), kolejność ramek HTTP/2, kolejność i wielkość liter nagłówków oraz ciasteczka sesyjne (_abck, ak_bmsc). Zwykłe wywołanie Pythona requests generuje fingerprint TLS, którego nie produkuje żadna prawdziwa przeglądarka — Akamai wykrywa to, zanim Twoje żądanie w ogóle dotrze do serwerów Walmartu.
PerimeterX/HUMAN działa po Akamai i wykonuje fingerprinting JavaScript (px.js), który sprawdza właściwości navigatora, renderowanie canvas, WebGL, kontekst audio oraz biometrie behawioralne (ruch myszy, prędkość przewijania, dynamikę klawiatury). Widoczną porażką jest słynne wyzwanie „Press & Hold” — przycisk, który trzeba przytrzymać przez około 10 sekund, podczas gdy zbierane są sygnały behawioralne. Oxylabs mówi wprost: „Walmart używa modelu CAPTCHA ‘Press & Hold’, oferowanego przez PerimeterX, który jest znany z tego, że niemal nie da się go rozwiązać z poziomu kodu.”
Naprawdę niebezpieczne jest ciche blokowanie. Walmart zwraca HTTP 200 z treścią CAPTCHA zamiast 403. ScrapingBee potwierdza: „Walmart zwraca kod statusu 200 OK nawet wtedy, gdy serwuje stronę CAPTCHA. Nie można polegać wyłącznie na kodzie statusu, żeby wiedzieć, czy żądanie się powiodło.” Skrypt z zadowoleniem parsuje HTML CAPTCHA jako „produkt nie został znaleziony” i idzie dalej. Połowa Twojego zbioru danych to śmieci, a Ty nawet o tym nie wiesz.
Do tego dochodzi problem danych zależnych od sklepu. Ceny i stany magazynowe Walmartu są zależne od lokalizacji i kontrolowane przez ciasteczka takie jak locDataV3 i assortmentStoreId. Bez właściwych ciasteczek dostajesz dane „domyślne, ogólnokrajowe”, które mogą wyglądać poprawnie, ale nie odpowiadają temu, co widzą prawdziwi klienci. Brak ciasteczek nie powoduje strony blokady — powoduje błędne dane bez widocznej awarii, a to jest jeszcze gorsze.
Trzy metody ekstrakcji danych z Walmartu (i jak się porównują)
Zanim przejdziemy do instrukcji krok po kroku, oto trzy główne podejścia do ekstrakcji. Większość poradników konkurencji opisuje tylko jedno lub dwa. Przejdę przez wszystkie trzy, żebyś mógł wybrać to, które pasuje do Twojej sytuacji.
| Metoda | Niezawodność | Kompletność danych | Trudność anty-botowa | Nakład utrzymania |
|---|---|---|---|---|
| HTML + BeautifulSoup | ⚠️ Niska (selektory psują się przy każdej publikacji) | Umiarkowana | Wysoka | Wysoki |
JSON z __NEXT_DATA__ | ✅ Dobra | Wysoka | Średnio-wysoka | Średni |
| Przechwytywanie wewnętrznego API | ✅ Najlepsza | Najwyższa (warianty, stany, recenzje) | Średnio-wysoka | Niski (ustrukturyzowany JSON) |
| Thunderbit (no-code) | ✅ Dobra | Wysoka | Niska (obsługuje AI) | Brak |
Parsowanie HTML to najgorsza opcja dla Walmartu — serwis działa na bundlach Next.js z hashowanymi nazwami klas CSS, które zmieniają się przy każdym wdrożeniu. Metoda z JSON-em __NEXT_DATA__ to pragmatyczny wybór, używany przez każdy poważny open-source’owy scraper Walmartu z lat 2024–2026. Przechwytywanie wewnętrznego API jest najpotężniejsze, ale wiąże się z zastrzeżeniami, które większość poradników pomija. A Thunderbit to właściwy wybór, gdy w ogóle nie potrzebujesz własnego pipeline’u.
Wypróbuj Thunderbit do scrapowania Walmartu
Konfiguracja środowiska Python do scrapowania Walmartu
Czego potrzebujesz:
- Poziom trudności: Średni
- Czas potrzebny: około 30 minut na konfigurację, plus czas na kodowanie
- Wymagania: Python 3.10+, pip, edytor kodu i (do użycia produkcyjnego) usługa proxy lub scraping API
Utwórz folder projektu i środowisko wirtualne:
mkdir walmart-scraper && cd walmart-scraper
python -m venv venv
source venv/bin/activate # W Windows: venv\Scripts\activate
Zainstaluj wymagane biblioteki:
pip install curl_cffi parsel beautifulsoup4 lxml
curl_cffi to standard na 2025 rok do scrapowania trudnych celów. To powiązanie z libcurl, które potrafi podszyć się pod dokładne fingerprinty TLS przeglądarki. Bright Data wyjaśnia: „Walmart używa fingerprintingu TLS jako części wykrywania botów, a samo ustawienie User-Agent, żeby zasymulować prawdziwą przeglądarkę, nie wystarczy, by to obejść.” Zwykłe requests lub httpx nie przejdą przez Akamai, niezależnie od tego, jakie nagłówki ustawisz. To właśnie curl_cffi z impersonate="chrome124" robi różnicę.
Przydadzą Ci się też json (wbudowany), csv (wbudowany), time, random i logging do wzorców produkcyjnych, które pokażę później.
Krok po kroku: jak scrapować strony produktów Walmartu w Pythonie
Krok 1: Pobierz stronę produktu Walmartu
Twoim pierwszym zadaniem jest wykonanie żądania HTTP, które nie zostanie od razu zablokowane. Oto kanoniczny zestaw nagłówków używany przez Scrapfly, Scrapingdog, Oxylabs i ScrapeOps w latach 2024–2026:
from curl_cffi import requests
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36"
),
"Accept": (
"text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,*/*;q=0.8"
),
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Referer": "https://www.google.com/",
}
session = requests.Session(impersonate="chrome124")
url = "https://www.walmart.com/ip/Apple-AirPods-Pro-2nd-Generation/1752657021"
response = session.get(url, headers=HEADERS)
Parametr impersonate="chrome124" wykonuje tu najcięższą pracę. Mówi curl_cffi, żeby dopasował dokładny TLS ClientHello Chrome 124, kolejność ramek HTTP/2 i sekwencję pseudo-nagłówków. Bez tego Akamai widzi fingerprint JA3 charakterystyczny dla Pythona i blokuje Cię, zanim żądanie dotrze do warstwy aplikacji Walmartu.
Jak wygląda zablokowana odpowiedź: Jeśli w tytule HTML odpowiedzi widzisz "Robot or human?" albo odpowiedź przekierowuje do walmart.com/blocked, zostałeś złapany. Trudność polega na tym, że Walmart często zwraca kod statusu 200 z treścią CAPTCHA — więc samo sprawdzanie response.ok nie wystarcza.
Do każdego zastosowania produkcyjnego lub powtarzalnego potrzebujesz proxy residentialnych. Adresy datacenter są natychmiast spalane przez system reputacji IP Akamai. Pełną strategię obsługi błędów i proxy omówię w sekcji produkcyjnej poniżej.
Krok 2: Parsuj dane produktu z JSON-a __NEXT_DATA__
Walmart.com to aplikacja Next.js, a renderowany po stronie serwera HTML osadza pełny payload hydracji w jednym tagu skryptu: <script id="__NEXT_DATA__" type="application/json">. To jest prawdziwa kopalnia danych.
Przewodnik Scrapfly z 2026 roku potwierdza: „W 2026 roku Walmart używa Next.js z ustrukturyzowanym JSON-em w tagach skryptu __NEXT_DATA__, co sprawia, że wyciąganie ukrytych danych jest bardziej niezawodne niż tradycyjne parsowanie selektorów CSS.” Każdy głośny open-source’owy scraper Walmartu — Scrapfly, Oxylabs, python-scrapy-playbook — używa właśnie tej metody.
Jak to wyciągnąć:
import json
from parsel import Selector
sel = Selector(text=response.text)
raw = sel.xpath('//script[@id="__NEXT_DATA__"]/text()').get()
data = json.loads(raw)
product = data["props"]["pageProps"]["initialData"]["data"]["product"]
idml = data["props"]["pageProps"]["initialData"]["data"].get("idml", {})
Większość poradników kończy tutaj. Poniżej znajdziesz pełną mapę ścieżek JSON dla pól, które naprawdę Cię interesują — zweryfikowaną na żywych stronach Walmartu w latach 2024–2026:
| Pole danych | Ścieżka JSON (w obrębie initialData) | Typ | Uwagi |
|---|---|---|---|
| Nazwa produktu | data > product > name | String | — |
| Marka | data > product > brand | String | — |
| Aktualna cena (liczba) | data > product > priceInfo > currentPrice > price | Float | Może się różnić w zależności od ciasteczka sklepu |
| Aktualna cena (tekst) | data > product > priceInfo > currentPrice > priceString | String | Sformatowana np. "$9.99" |
| Krótki opis | data > product > shortDescription | String HTML | Parsuj przez BeautifulSoup, jeśli chcesz tekst |
| Długi opis | data > idml > longDescription | String HTML | Jest w idml, NIE w product — to pułapka, w którą wpadają starsze poradniki |
| Wszystkie obrazy | data > product > imageInfo > allImages | Tablica | Lista obiektów {id, url} |
| Średnia ocena | data > product > averageRating | Float | Klucz to averageRating, nie stare rating |
| Liczba recenzji | data > product > numberOfReviews | Integer | — |
| Warianty | data > product > variantCriteria | Tablica | Grupy opcji (rozmiar, kolor) |
| Dostępność | data > product > availabilityStatus | String | IN_STOCK, OUT_OF_STOCK, LIMITED_STOCK |
| Sprzedawca | data > product > sellerDisplayName | String | — |
| Producent | data > product > manufacturerName | String | — |
Ścieżka longDescription to jedna z pułapek, które łapią ludzi. Post ScrapeHero z 2023 roku umieszczał ją pod product.longDescription, ale źródła z 2024+ konsekwentnie pokazują ją w sąsiednim kluczu idml. Zawsze najpierw sprawdzaj idml.longDescription, a dla starszych stron ustaw fallback na product.longDescription.
Oto bezpieczny wzorzec ekstrakcji z użyciem łańcuchów .get():
def extract_product(data):
product = data["props"]["pageProps"]["initialData"]["data"]["product"]
idml = data["props"]["pageProps"]["initialData"]["data"].get("idml", {})
price_info = product.get("priceInfo", {})
current_price = price_info.get("currentPrice", {})
image_info = product.get("imageInfo", {})
return {
"name": product.get("name"),
"brand": product.get("brand"),
"price": current_price.get("price"),
"price_string": current_price.get("priceString"),
"short_desc": product.get("shortDescription"),
"long_desc": idml.get("longDescription", product.get("longDescription")),
"images": [img.get("url") for img in image_info.get("allImages", [])],
"rating": product.get("averageRating"),
"review_count": product.get("numberOfReviews"),
"variants": product.get("variantCriteria"),
"availability": product.get("availabilityStatus"),
"seller": product.get("sellerDisplayName"),
"manufacturer": product.get("manufacturerName"),
}
Dla użytkowników, którzy w ogóle nie chcą zajmować się nawigacją po ścieżkach JSON, AI Thunderbit automatycznie identyfikuje i strukturyzuje te pola — bez ręcznego mapowania ścieżek. Klikasz „AI Suggest Fields”, narzędzie czyta stronę i dostajesz tabelę. Ale jeśli budujesz własny pipeline, mapa powyżej będzie Twoim punktem odniesienia.
Krok 3: Przechwyć wewnętrzne endpointy API Walmartu, aby uzyskać bogatsze dane
Żaden artykuł konkurencji nie opisuje tej metody poprawnie. To najpotężniejsza ścieżka ekstrakcji — i najbardziej skomplikowana.
Frontend Walmartu korzysta z sfederowanego backendu GraphQL zbudowanego na Apollo Gateway. Endpointy znajdują się pod www.walmart.com/orchestra/*:
/orchestra/pdp/graphql/...— hydratacja szczegółów produktu + przełączanie wariantów/orchestra/snb/graphql/...— paginacja search-n-browse/orchestra/reviews/graphql/...— recenzje z paginacją
Zwracają czysty, ustrukturyzowany JSON z danymi, które __NEXT_DATA__ czasem ucina — ceny na poziomie wariantów, bieżące stany magazynowe, pełną paginację recenzji.
Haczyk, o którym blogi zwykle tylko wspominają: Walmart używa Apollo persisted queries. Treść żądania zawiera tylko hash SHA-256 (persistedQuery.sha256Hash), a nie tekst zapytania. Jeśli hash nie jest znany serwerowi, dostajesz PersistedQueryNotFound. Walmart rotuje te hashe przy wdrożeniach. Dlatego żaden z głośnych open-source’owych scraperów Walmartu nie publikuje kodu /orchestra/, który dałoby się po prostu skopiować i wkleić.
Praktyczna, uczciwa wersja tej metody to ćwiczenie w DevTools:
- Otwórz stronę produktu Walmartu w Chrome
- Otwórz DevTools → zakładka Network, filtruj po „Fetch/XHR”
- Przeglądaj stronę normalnie — klikaj warianty, przewijaj do recenzji, zmieniaj lokalizację sklepu
- Szukaj żądań do endpointów
/orchestra/*, które zwracają JSON z danymi produktu - Kliknij prawym przyciskiem na żądanie → „Copy as cURL”
- Przekształć polecenie cURL do Pythona za pomocą
curl_cffi
Tak wygląda odtworzone wywołanie API:
import json
from curl_cffi import requests
session = requests.Session(impersonate="chrome124")
# Najpierw rozgrzej sesję, odwiedzając stronę produktu
session.get("https://www.walmart.com/ip/some-product/1234567", headers=HEADERS)
# Potem odtwórz wewnętrzne wywołanie API (skopiowane z DevTools)
api_url = "https://www.walmart.com/orchestra/pdp/graphql"
api_headers = {
**HEADERS,
"accept": "application/json",
"content-type": "application/json",
"referer": "https://www.walmart.com/ip/some-product/1234567",
"wm_qos.correlation_id": "your-copied-correlation-id",
}
payload = {
# Wklej dokładnie treść żądania z DevTools
"variables": {"productId": "1234567"},
"extensions": {
"persistedQuery": {
"version": 1,
"sha256Hash": "the-hash-you-copied"
}
}
}
api_response = session.post(api_url, headers=api_headers, json=payload)
api_data = api_response.json()
Krok rozgrzania sesji jest kluczowy. Ciasteczka PerimeterX Walmartu (_px3, _pxhd, ACID) muszą zostać ustawione przez pierwsze pobranie HTML, zanim wywołanie API zadziała. Bez nich dostaniesz 412 albo 403.
Kiedy używać tej metody: Gdy potrzebujesz danych, których nie ma w __NEXT_DATA__ — głębokich cen wariantów, recenzji z paginacją poza pierwszą paczką albo bieżących stanów magazynowych. W większości przypadków __NEXT_DATA__ wystarcza i jest znacznie prostsze.
Scraping wyników wyszukiwania i wielu stron na Walmart
Wyniki wyszukiwania działają podobnie jak __NEXT_DATA__, ale z inną ścieżką JSON:
search_url = "https://www.walmart.com/search?q=laptops&page=1"
response = session.get(search_url, headers=HEADERS)
sel = Selector(text=response.text)
raw = sel.xpath('//script[@id="__NEXT_DATA__"]/text()').get()
data = json.loads(raw)
search_result = data["props"]["pageProps"]["initialData"]["searchResult"]
items = search_result["itemStacks"][0]["items"]
# Odfiltruj sponsorowane produkty
organic_items = [i for i in items if i.get("__typename") == "Product"]
for item in organic_items:
print(item.get("name"), item.get("priceInfo", {}).get("currentPrice", {}).get("price"))
Paginacja działa przez zwiększanie parametru page: &page=1, &page=2 itd. Ale jest tu nieudokumentowany limit: Walmart ogranicza wyniki wyszukiwania do 25 stron niezależnie od rzeczywistej liczby wyników. Scrapfly to potwierdza: „Walmart ustawia maksymalną liczbę dostępnych stron wyników na 25, niezależnie od całkowitej liczby stron.”
Obejścia, jeśli chcesz zejść głębiej:
- Zmiana kolejności sortowania: uruchom to samo zapytanie z
&sort=price_low, a potem z&sort=price_high, aby uzyskać około 50 stron pokrycia - Dzielenie po przedziale cenowym: dodaj
&min_price=X&max_price=Y, aby rozbić katalog na mniejsze okna - Dzielenie po kategoriach: szukaj w konkretnych kategoriach, a nie w całym serwisie
Zwróć uwagę, że itemStacks jest tablicą. Scrapfly na sztywno używa [0] w swoim repo, ale strony kategorii i przeglądania czasem zawierają wiele stosów („Top picks”, „More results”). Solidny wzorzec iteruje po wszystkich stosach:
for stack in search_result.get("itemStacks", []):
for item in stack.get("items", []):
if item.get("__typename") == "Product":
# przetwórz element
pass
Warto też zauważyć, że robots.txt Walmartu blokuje /search. Strony szczegółów produktu (/ip/...) i większość stron kategorii (/cp/...) nie są zablokowane. Jeśli martwisz się zgodnością, zacznij od stron produktów i drzew kategorii, a nie od wyszukiwania.
Nie pozwól, by ciche blokady zniszczyły Twoje dane: obsługa błędów gotowa do produkcji
Większość poradników tutaj się rozsypuje. Pokazują, jak pobrać jedną stronę, sparsować jeden produkt i tyle. W produkcji pobierasz tysiące stron, a Walmart aktywnie próbuje Cię zatrzymać. Różnica między demonstracyjnym scraperem a scraperem, który naprawdę działa, polega na tym, jak radzi sobie z błędami.
Wykrywaj ciche blokady, zanim skażą Twoje dane
Najważniejszą funkcją w scraperze Walmartu jest detektor blokady. Na podstawie zgodnego stanowiska dostawców, takich jak ScrapingBee, Scrapingdog, Oxylabs i Decodo, potrzebujesz czterech niezależnych testów:
BLOCK_MARKERS = (
"Robot or human",
"Press & Hold",
"Press & Hold",
"px-captcha",
"perimeterx",
)
def is_walmart_blocked(response) -> bool:
# 1. Przekierowanie do dedykowanego endpointu blokady
if "/blocked" in str(response.url):
return True
# 2. Twarde kody statusu
if response.status_code in (403, 412, 428, 429, 503):
return True
# 3. 200 OK z treścią CAPTCHA (przypadek cichej blokady)
body = response.text or ""
if any(m.lower() in body.lower() for m in BLOCK_MARKERS):
return True
# 4. Kontrola długości odpowiedzi — prawdziwe PDP mają 300–900 KB
if len(response.content) < 50_000 and "/ip/" in str(response.url):
return True
return False
Ten czwarty test — długość odpowiedzi — łapie sytuacje, w których Walmart zwraca uproszczoną stronę bez oczywistych markerów CAPTCHA, ale też bez danych produktu, których potrzebujesz.
Logika ponowień z wykładniczym backoffem i jitterem
Gdy żądanie się nie powiedzie, nie chcesz od razu bombardować Walmartu kolejnymi próbami. Standardowy wzorzec używa wykładniczego backoffu z jitterem, żeby rozproszyć ponowienia:
import time
import random
import logging
from curl_cffi import requests as cffi_requests
log = logging.getLogger("walmart")
def fetch_with_retry(session, url, max_retries=5, base_delay=2, max_delay=60):
for attempt in range(max_retries):
try:
response = session.get(url, headers=HEADERS, timeout=15)
if response.status_code in (429, 503):
raise Exception(f"Throttled: {response.status_code}")
if is_walmart_blocked(response):
raise Exception("Wykryto cichą blokadę")
return response
except Exception as e:
if attempt == max_retries - 1:
raise
wait = min(max_delay, base_delay * (2 ** attempt)) + random.uniform(0, 3)
log.warning(f"Próba {attempt + 1} nie powiodła się: {e}. Ponawianie za {wait:.1f}s")
time.sleep(wait)
return None
Jitter (random.uniform(0, 3)) nie jest kosmetyką — rozprasza wywołania tak, by cała flota scraperów nie ponawiała prób w tej samej sekundzie i nie wyzwalała detektorów prędkości Akamai.
Limitowanie tempa
Zarówno Thunderbit, jak i Scrape.do dochodzą do tego samego wniosku w przypadku Walmartu: losowy odstęp 3–6 sekund na żądanie. Jak piszą: „ograniczaj tempo żądań, czekając 3–6 sekund między ładowaniami stron i losując opóźnienia”.
import time
import random
def rate_limited_fetch(session, url):
response = fetch_with_retry(session, url)
time.sleep(random.uniform(3.0, 6.0))
return response
Na większą skalę rozważ użycie aiolimiter do asynchronicznego limitowania tempa:
from aiolimiter import AsyncLimiter
limiter = AsyncLimiter(max_rate=10, time_period=60) # 10 żądań na minutę
Walidacja danych
Nawet jeśli odpowiedź nie jest zablokowana, sparsowane dane mogą być błędne (zły sklep, zdegradowany payload). Zweryfikuj je przed zapisaniem do pliku wyjściowego:
def validate_product(product):
"""Zwraca True, jeśli dane produktu wyglądają wiarygodnie."""
if not product.get("name"):
return False
price = (product.get("priceInfo") or {}).get("currentPrice", {}).get("price")
if not isinstance(price, (int, float)) or price <= 0:
return False
if product.get("availabilityStatus") not in ("IN_STOCK", "OUT_OF_STOCK", "LIMITED_STOCK"):
return False
return True
Logowanie sesji
Śledź współczynnik skuteczności dla każdej sesji. Gdy przez 10 minut spadnie poniżej 80%, coś się zmieniło — albo adres IP jest spalony, albo wygasły ciasteczka, albo Walmart wdrożył nową regułę anty-botową.
class ScrapeMetrics:
def __init__(self):
self.total = 0
self.success = 0
self.blocks = 0
self.errors = 0
def record(self, result):
self.total += 1
if result == "success":
self.success += 1
elif result == "blocked":
self.blocks += 1
else:
self.errors += 1
@property
def success_rate(self):
return (self.success / self.total * 100) if self.total > 0 else 0
def check_health(self):
if self.total > 20 and self.success_rate < 80:
log.critical(f"Współczynnik skuteczności spadł do {self.success_rate:.1f}% — rozważ rotację proxy lub wstrzymanie")
Nieefektowne. Ale właśnie to utrzymuje Twoje dane w czystości.
Python DIY vs. Scraping API vs. No-Code: jak wybrać właściwe podejście do scrapowania Walmartu
Wielu developerów od razu pisze własny scraper, nie zastanawiając się, czy to w ogóle właściwy wybór. ScrapeOps ocenia Walmart na 9/10 trudności. Użytkownicy forum opisują to jako „w zasadzie 9/10” i zastanawiają się, „czy dedykowane API do web scrapingu nie byłoby przesadą”. Odpowiedź zależy od skali, budżetu i możliwości inżynieryjnych.
| Czynnik | DIY Python (requests + proxy) | Scraping API (Oxylabs, Bright Data itd.) | Narzędzie no-code (Thunderbit) |
|---|---|---|---|
| Czas do pierwszego wiersza | Godziny | 15–60 min | Około 2 min |
| Czas do produkcji | 40–80 godz. | 4–16 godz. | Około 30 min |
| Obsługa anty-botowa | Ty zarządzasz (trudne) | Obsługiwana przez dostawcę | Obsługiwana automatycznie |
| Koszt przy małej skali (<1 tys. stron/mies.) | Niski (proxy ok. 4–8 USD/GB) | Plany od 40–49 USD/mies. | 0–15 USD/mies. |
| Koszt przy skali (100 tys.+ stron/mies.) | Niższy na żądanie | Wyższy na żądanie | Zależy |
| Personalizacja | Pełna kontrola | Parametry API | Ograniczona przez UI/pola |
| Bieżące utrzymanie | 4–8 godz./mies. | Bliskie zeru | Brak (AI się dostosowuje) |
| Najlepsze dla | Developerów budujących własne pipeline’y | Średniej skali scrapingu produkcyjnego | Użytkowników biznesowych, szybkich jednorazowych ekstrakcji |
Kiedy DIY Python ma sens
DIY wygrywa, gdy już masz umowę na proxy, potrzebujesz ścisłej kontroli nad nagłówkami, targetowaniem kodów pocztowych lub kohortami sprzedawców, indeksujesz miliony stron miesięcznie, więc opłaty API za rekord się kumulują, albo potrzebujesz wdrożenia on-prem lub gwarancji zgodności. Cena jest jednak realna: produkcyjny spider Scrapy z paginacją, retry, rotacją proxy, TLS impersonation i wieloma schematami typów stron wymaga 40–80 godzin pracy senior Python developera, plus 4–8 godzin utrzymania miesięcznie, gdy Walmart rotuje fingerprinty.
Kiedy scraping API oszczędza czas
Scraping API obsługują warstwę anty-botową za Ciebie. Benchmarki ScrapeOps pokazują skuteczność 99% dla Zyte API i 98% dla Scrape.do na Walmartu. Ceny wejściowe zaczynają się od 40–49 USD/mies. dla narzędzi takich jak ScraperAPI, Oxylabs i Scrapingdog. Jeśli masz zespół 2–5 inżynierów i scrapujesz od 10 tys. do 1 mln stron miesięcznie, API niemal zawsze będzie właściwym wyborem. Płacisz więcej za żądanie, ale masz zerowe utrzymanie.
Kiedy no-code jest właściwym wyborem
Thunderbit pasuje do zupełnie innego profilu. Jeśli jesteś PM-em, analitykiem albo operatorem e-commerce i potrzebujesz danych produktowych Walmartu w arkuszu dziś po południu — a nie w następnym sprincie — narzędzie no-code jest po prostu uczciwą odpowiedzią.
Workflow wygląda tak: zainstaluj rozszerzenie Thunderbit do Chrome, przejdź na stronę produktu lub wyszukiwania Walmartu, kliknij „AI Suggest Fields”, a AI Thunderbit odczyta stronę i zasugeruje kolumny (nazwa produktu, cena, ocena itd.). Kliknij „Scrape”, a dane pojawią się w tabeli. Eksportuj do Excela, Google Sheets, Airtable lub Notion — wszystko za darmo, bez paywalla.
Thunderbit obsługuje anty-bot w chmurze, więc nie musisz zajmować się CAPTCHA, proxy ani fingerprintingiem TLS. AI automatycznie dostosowuje się do zmian układu, więc nie ma utrzymania. Dla użytkowników, którzy w ogóle nie chcą nawigować po ścieżkach JSON, to najprostsza droga.
Szczere ograniczenia: Thunderbit nie jest zbudowany do ponad 100 tys. stron dziennie. Budżety kredytowe i limity chmurowe sprawiają, że masowy ingest jest mniej opłacalny niż surowe API. Nie możesz też przypisać konkretnego kodu pocztowego ani ASN, chyba że narzędzie to obsługuje. Do długotrwałych, wysokowydajnych pipeline’ów nadal lepszy będzie DIY albo scraping API.
Szacunkowa cena: 1 000 wierszy produktów Walmartu w Thunderbit kosztuje około 2 000 kredytów (około 0,60–1,10 USD w planach Starter/Pro). To porównywalne z API Walmartu od Oxylabs i tańsze niż większość amatorskich scraping API przy niskim wolumenie. Sprawdź cennik Thunderbit, aby poznać aktualne szczegóły.
Scrapuj dane produktowe Walmartu z pomocą AI Get Started Free
Eksport danych Walmartu po scrapowaniu
Gdy już masz dane, potrzebujesz miejsca, gdzie będą użyteczne. Trzy formaty pokrywają większość potrzeb:
CSV — najprostszy format, który analitycy faktycznie otwierają:
import csv
def export_csv(products, filename="walmart_products.csv"):
fieldnames = ["name", "price", "availability", "rating", "review_count", "seller", "url"]
with open(filename, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames, quoting=csv.QUOTE_MINIMAL)
writer.writeheader()
for p in products:
writer.writerow({k: p.get(k) for k in fieldnames})
Użyj kodowania utf-8-sig, żeby zapewnić zgodność z Excelem. Znacznik BOM zapobiega psuciu znaków specjalnych.
JSONL — format produkcyjny dla pipeline’ów scrapujących:
import json
import gzip
def export_jsonl(products, filename="walmart_products.jsonl.gz"):
with gzip.open(filename, "at", encoding="utf-8") as f:
for p in products:
f.write(json.dumps(p, ensure_ascii=False) + "\n")
JSONL jest odporny na awarie (przerwany zapis powoduje utratę tylko ostatniej linii), można go strumieniować przy stałym zużyciu pamięci i zachowuje zagnieżdżone dane, takie jak warianty i recenzje.
Excel — do jednorazowych przekazań dla analityka:
from openpyxl import Workbook
def export_excel(products, filename="walmart_products.xlsx"):
wb = Workbook(write_only=True)
ws = wb.create_sheet("Products")
ws.append(["Nazwa", "Cena", "Dostępność", "Ocena", "Recenzje", "Sprzedawca"])
for p in products:
ws.append([p.get("name"), p.get("price"), p.get("availability"),
p.get("rating"), p.get("review_count"), p.get("seller")])
wb.save(filename)
Thunderbit obsługuje eksport także dla osób nietechnicznych: jednym kliknięciem do Google Sheets, Airtable, Notion, Excela, CSV i JSON — wszystko za darmo w podstawowym planie. Do stałego monitoringu funkcja zaplanowanego scrapera Thunderbit może uruchamiać cykliczne ekstrakcje automatycznie.
Jedna uwaga dotycząca harmonogramu: nie używaj GitHub Actions do scrapowania Walmartu. Runnery GitHub Actions działają na zakresach IP Azure, które anty-bot Walmartu blokuje natychmiast. Użyj APScheduler na VPS albo kieruj cały ruch przez proxy residentialne.
Wskazówki prawne i etyczne dotyczące scrapowania Walmartu
Użytkownicy forum wprost wyrażają tę obawę: „Nie mam nic przeciwko zabawie w kotka i myszkę z developerami, ale nie chcę bawić się z ich działem prawnym.”
Warunki korzystania z Walmartu wprost zabraniają używania „jakiegokolwiek robota, spidera… lub innego ręcznego albo automatycznego urządzenia do pobierania, indeksowania, ‘scrapowania’, ‘data mining’ lub w inny sposób gromadzenia materiałów” bez „wyraźnej, uprzedniej pisemnej zgody”.
robots.txt Walmartu blokuje /search, /account, /api/ i dziesiątki wewnętrznych endpointów. Strony szczegółów produktu (/ip/...) i recenzje (/reviews/product/) nie są zablokowane.
Precedens hiQ v. LinkedIn (9. okręg, 2022) ustanowił, że scrapowanie publicznie dostępnych danych raczej nie narusza federalnej ustawy CFAA. Ale ten sam sąd później orzekł, że hiQ naruszyło User Agreement LinkedIn i nałożył na nie ugodę na 500 000 dolarów. Nowsze orzeczenia z 2024 roku (Meta v. Bright Data, X Corp. v. Bright Data) jeszcze bardziej zawęziły CFAA i stworzyły obrony oparte na preempcji praw autorskich, ale te wyroki opierały się na konkretnych zapisach ToU, które nie przekładają się wprost na Walmart.
Praktyczne zasady: Nie przeciążaj serwerów. Szanuj limity tempa. Nie scrapuj danych osobowych ani danych użytkowników. Korzystaj z danych odpowiedzialnie. Scrapowanie publicznych stron produktów Walmartu z umiarkowaną częstotliwością na potrzeby prywatnych badań to zupełnie inny profil ryzyka niż scrapowanie na skalę komercyjną wbrew warunkom Walmartu. Jeśli budujesz produkt oparty na danych Walmartu, porozmawiaj z prawnikiem i sprawdź oficjalne API afiliacyjne i dla sprzedawców.
Zastrzeżenie: To są informacje edukacyjne, a nie porada prawna.
Podsumowanie i najważniejsze wnioski
Scrapowanie Walmartu w Pythonie to wyzwanie o trudności 9/10 ze względu na podwójny stos anty-botowy Akamai + PerimeterX. Nie jest niemożliwe — ale potrzebujesz właściwych narzędzi i wzorców.
Najważniejsze wnioski:
- Ekstrakcja JSON z
__NEXT_DATA__to najbardziej pragmatyczny wybór dla większości zastosowań. To z niego korzysta każdy poważny open-source’owy scraper Walmartu z lat 2024–2026. Bazowa ścieżka toprops.pageProps.initialData.data.productdla PDP orazsearchResult.itemStacksdla wyszukiwania/przeglądania. curl_cffizimpersonate="chrome124"jest obowiązkowe. Zwykłerequestsanihttpxnie przejdą przez fingerprinting TLS Akamai, niezależnie od nagłówków.- Ciche blokady są prawdziwym zagrożeniem. Walmart zwraca 200 OK z treścią CAPTCHA. Sprawdzaj treść odpowiedzi, nie tylko kody statusu.
- Scrapery produkcyjne potrzebują czegoś więcej niż kodu na szczęśliwą ścieżkę. Wykładniczy backoff z jitterem, wykrywanie blokad na czterech sygnałach, limitowanie tempa do 3–6 sekund na żądanie, walidacja danych i monitorowanie zdrowia sesji są niezbędne.
- Przechwytywanie wewnętrznego API przez
/orchestra/*jest potężne, ale kruche. Używaj go jako ćwiczenia w DevTools dla konkretnych potrzeb danych, nie jako głównej metody ekstrakcji. - Walmart ogranicza wyniki wyszukiwania do 25 stron. Rozszerz pokrycie przez zmianę sortowania i dzielenie po zakresie cen.
- Wybierz podejście uczciwie: Python DIY dla developerów z niestandardowymi potrzebami i dużym wolumenem. Scraping API dla średnich zespołów bez inżyniera scrapującego. Thunderbit dla użytkowników biznesowych, którzy chcą mieć dane w Google Sheets jeszcze dziś po południu.
Jeśli chcesz wypróbować ścieżkę no-code, rozszerzenie Thunderbit do Chrome ma darmowy plan — możesz scrapować kilka stron Walmartu i samodzielnie zobaczyć wyniki. Jeśli wybierasz Pythona, wzorce kodu z tego artykułu zostały przetestowane produkcyjnie. Tak czy inaczej, masz już mapę zabezpieczeń Walmartu i trzy drogi, by je obejść.
Więcej o technikach web scrapingu znajdziesz w naszych poradnikach: jak scrapować dane z internetu w Pythonie, najlepsze automatyczne narzędzia do web scrapingu oraz web scraping bez blokad. Możesz też obejrzeć tutoriale na kanale Thunderbit na YouTube.
FAQ
Czy scrapowanie danych produktowych Walmartu jest legalne?
Warunki korzystania z Walmartu zabraniają automatycznego scrapowania bez pisemnej zgody. Orzeczenie 9. okręgu w sprawie hiQ v. LinkedIn (2022) ustaliło, że federalna CFAA raczej nie ma zastosowania do scrapowania publicznych stron, ale ta sama sprawa zakończyła się wyrokiem za naruszenie umowy na 500 000 dolarów przeciwko scraperowi. Scrapowanie publicznych stron produktów w umiarkowanym tempie na potrzeby badań własnych wiąże się z zupełnie innym poziomem ryzyka niż ekstrakcja na skalę komercyjną. Skonsultuj się z prawnikiem, jeśli budujesz biznes na danych Walmartu.
Dlaczego mój scraper Walmartu ciągle jest blokowany?
Najczęstsze przyczyny to: używanie zwykłego requests lub httpx (które generują fingerprint TLS charakterystyczny dla Pythona i Akamai wykrywa go natychmiast), brak lub błędne nagłówki, brak rotacji proxy, zbyt szybkie tempo żądań — szybciej niż 3–6 sekund na stronę — oraz brak ciasteczek sesyjnych (_px3, _abck, locDataV3). Przejdź na curl_cffi z impersonate="chrome124", używaj proxy residentialnych i wdroż wzorce wykrywania blokad i ponowień opisane w tym artykule.
Jakie dane mogę scrapować z Walmartu w Pythonie?
Nazwy produktów, ceny (aktualne i rollback), obrazy, krótkie i długie opisy, oceny, liczbę recenzji, status dostępności, nazwy sprzedawców, informacje o producencie, opcje wariantów (rozmiar, kolor) oraz pozycję w kategorii. Przy metodzie __NEXT_DATA__ wszystkie te dane są dostępne jako ustrukturyzowany JSON. Przechwytywanie wewnętrznego API może dodatkowo zwrócić ceny na poziomie wariantów, bieżące stany magazynowe i dane recenzji z paginacją.
Czy do scrapowania Walmartu potrzebuję proxy?
Tak, przy każdym użyciu produkcyjnym lub powtarzalnym. Systemy anty-bot Walmartu konsekwentnie blokują zwykłe żądania — nawet przy idealnych nagłówkach adres IP spoza sieci residential zostanie oznaczony przez system reputacji IP Akamai. Wymagane są proxy residentialne lub mobilne. Adresy datacenter są spalane niemal natychmiast. Przyjmij budżet około 3–17 dolarów za 1 000 stron, zależnie od dostawcy proxy i planu.
Czy mogę scrapować Walmart bez pisania kodu?
Tak. Thunderbit to rozszerzenie Chrome oparte na AI, które scrapuje Walmart w dwóch kliknięciach: „AI Suggest Fields” do automatycznego wykrywania kolumn danych produktowych, a potem „Scrape” do wyciągnięcia danych. Obsługuje wyzwania anty-bot w chmurze i eksportuje bezpośrednio do Excela, Google Sheets, Airtable lub Notion — wszystko za darmo. Najlepiej sprawdza się dla analityków, PM-ów i użytkowników biznesowych, którzy potrzebują danych szybko, bez budowania własnego pipeline’u. Przy dużej skali lub bardzo niestandardowym scrapowaniu lepszy będzie nadal Python albo scraping API.
Wypróbuj Thunderbit do AI scrapowania Walmartu Get Started Free
Dowiedz się więcej


