如何用 Python 抓取 Walmart 数据(还不被封)

最后更新于 April 15, 2026

Walmart 有些商品的价格会在 。如果你曾经试着用程序去追踪这些变化,就会知道有多折磨:脚本跑了 20 分钟,结果开始悄悄把 CAPTCHA 页面当成正常的 200 OK 返回给你。

在 Thunderbit 的数据提取工作里,我花了大量时间研究 Walmart 的反爬机制,也想把这些经验完整分享出来——哪些方法在 2025 年真的还管用,哪些“静默失败”会悄悄污染你的数据,以及在自己写爬虫、付费用抓取 API、还是直接上无代码工具之间,到底该怎么权衡。这篇指南会覆盖三种提取方式(HTML 解析、__NEXT_DATA__ JSON、内部 API 拦截)、很多教程完全不会讲的生产级错误处理,以及一个务实的选择框架,帮你判断哪条路最适合你。不管你是在写 Python,还是只想在午饭前拿到一份装满价格的表格,这里都能找到答案。

为什么要用 Python 抓取 Walmart?

Walmart 是全球营收最高的零售商——在 2025 财年营收达到 ,并且 。网站上大约有 ,而 Walmart CFO 还提到平台上有 。其中大约 ,这意味着目录变化非常快——卖家更替、变体变化、库存每天都在波动。

walmart_stats_670d06c6bd.png

正因为这种波动,抓取数据才有价值。季度报表看不到夜间爬取能抓到的变化。以下是我最常见的应用场景:

应用场景使用人群提取内容
竞品价格监控电商运营、调价工具价格、促销、MAP 合规
商品目录补全销售与商品团队描述、图片、规格、变体
库存可用性跟踪供应链、Dropship 卖家库存状态、卖家信息
市场调研与趋势分析市场、产品经理评分、评论、类目结构
潜客开发销售团队卖家名称、商品数量、类目

仅竞品价格监控软件市场在 2025 年就达到 ,并预计到 2033 年增长到 50.9 亿美元。消费者行为也在推动这个需求: ,而且 83% 的人会跨多个网站比较价格。

Python 是这类工作的默认语言。Apify 的 2026 基础设施报告显示, ,而核心库 requests 每周下载量达到 。如果你在做任何规模的抓取,基本上用的都是 Python。

为什么 Walmart 是最难抓取的网站之一

Walmart 难抓,主要是因为它把 两套商业反爬产品串联在一起 负责边缘 WAF 和 TLS 指纹识别,接着是 负责 JavaScript 行为挑战层。Scrape.do 把这种组合称为“极其罕见,而且非常难绕过”。

walmart_antibot_3d67d0119c.png

,仅 Akamai 一项就是 9/10。按我的经验,这个评分很准确。

你实际面对的是这些东西:

Akamai Bot Manager 会检查你的 TLS 指纹(JA3/JA4 hash)、HTTP/2 帧顺序、请求头顺序和大小写,以及会话 cookie(_abckak_bmsc)。普通 Python requests 发出的 TLS 指纹,和真实浏览器完全不是一个样子——Akamai 在请求到达 Walmart 服务器之前就会把它识别出来。

PerimeterX/HUMAN 则在 Akamai 之后运行,它会执行 JavaScript 指纹识别(px.js),检查 navigator 属性、canvas 渲染、WebGL、音频上下文,以及行为生物特征(鼠标移动、滚动速度、按键节奏)。最典型的失败表现,就是那个臭名昭著的 ——你要按住按钮大约 10 秒,同时系统采集你的行为信号。Oxylabs 的说法很直接:“Walmart 使用的是 PerimeterX 提供的 ‘Press & Hold’ CAPTCHA 模式,几乎不可能靠代码来解决。”

真正危险的是 静默封锁。Walmart 不是返回 403,而是直接返回 HTTP 200,但内容是 CAPTCHA 页面:“Walmart 即使返回 CAPTCHA 页面,也会给你 200 OK 状态码。你不能只靠状态码判断请求是否成功。” 你的脚本会心安理得地把 CAPTCHA HTML 当成“商品不存在”,然后继续跑。最后一半数据都是脏的,而你根本不知道。

还有一个问题是 门店范围数据。Walmart 的价格和库存是跟地区相关的,受 locDataV3assortmentStoreId 这类 cookie 控制。如果 cookie 不对,你看到的是“默认全国数据”,它看起来很完整,但和真实用户看到的结果并不一致。缺少这些 cookie 不会弹错误页,只会给你 错误但看不出来的数据,这比直接被封更糟。

三种从 Walmart 提取数据的方法(以及它们的对比)

在进入实操之前,先看看三种主要的提取方式。大多数竞争对手的教程只讲一两种,我会把三种都讲清楚,这样你可以按自己的情况选择最合适的方案。

方法可靠性数据完整度反爬难度维护成本
HTML + BeautifulSoup⚠️ 低(选择器会随着部署失效)中等
__NEXT_DATA__ JSON✅ 较好中高中等
内部 API 拦截✅ 最佳最高(变体、库存、评论)中高低(结构化 JSON)
Thunderbit(无代码)✅ 较好低(AI 代劳)

对 Walmart 来说,HTML 解析是最差的选择——网站使用的是 Next.js,并且 CSS 类名带哈希,每次部署都会变。__NEXT_DATA__ JSON 方法则更务实,也是 2024–2026 年几乎所有严肃开源 Walmart 爬虫的主流方案。内部 API 拦截功能最强,但也有很多教程一笔带过的限制。至于 Thunderbit,则适合你根本不想自己搭管线的场景。

搭建 Python 环境来抓取 Walmart

你需要准备这些东西:

  • 难度: 中等
  • 所需时间: 环境配置约 30 分钟,再加上编码时间
  • 你需要: Python 3.10+、pip、代码编辑器,以及(用于生产环境)代理服务或抓取 API

先创建项目目录和虚拟环境:

1mkdir walmart-scraper && cd walmart-scraper
2python -m venv venv
3source venv/bin/activate  # On Windows: venv\Scripts\activate

安装所需库:

1pip install curl_cffi parsel beautifulsoup4 lxml

curl_cffi 是 2025 年抓取高难度站点的标准工具。它是一个 libcurl 绑定,可以精确模拟浏览器的 TLS 指纹。:“Walmart 会把 TLS 指纹识别作为反爬的一部分,就算把 User-Agent 改成真实浏览器,也绕不过去。” 单靠 requestshttpx,无论你怎么设置请求头,都过不了 Akamai。真正起作用的是带 impersonate="chrome124"curl_cffi

另外你还会用到内置的 jsoncsv,以及 timerandomlogging,后面我们会讲到生产级写法。

分步实操:用 Python 抓取 Walmart 商品页

第 1 步:请求 Walmart 商品页面

你的第一步,是发出一个不会立刻被拦的 HTTP 请求。下面是 2024–2026 年 Scrapfly、Scrapingdog、Oxylabs 和 ScrapeOps 常用的一套标准请求头:

1from curl_cffi import requests
2HEADERS = {
3    "User-Agent": (
4        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
5        "AppleWebKit/537.36 (KHTML, like Gecko) "
6        "Chrome/124.0.0.0 Safari/537.36"
7    ),
8    "Accept": (
9        "text/html,application/xhtml+xml,application/xml;q=0.9,"
10        "image/avif,image/webp,*/*;q=0.8"
11    ),
12    "Accept-Language": "en-US,en;q=0.9",
13    "Accept-Encoding": "gzip, deflate, br",
14    "Upgrade-Insecure-Requests": "1",
15    "Sec-Fetch-Dest": "document",
16    "Sec-Fetch-Mode": "navigate",
17    "Sec-Fetch-Site": "none",
18    "Sec-Fetch-User": "?1",
19    "Referer": "https://www.google.com/",
20}
21session = requests.Session(impersonate="chrome124")
22url = "https://www.walmart.com/ip/Apple-AirPods-Pro-2nd-Generation/1752657021"
23response = session.get(url, headers=HEADERS)

impersonate="chrome124" 这个参数是核心。它让 curl_cffi 精确匹配 Chrome 124 的 TLS ClientHello、HTTP/2 帧顺序,以及伪头部顺序。如果没有它,Akamai 会看到一个 Python 特征的 JA3 hash,并在请求到达 Walmart 应用层之前就将其拦截。

被封后的响应长什么样: 如果你在 HTML 标题里看到 "Robot or human?",或者页面重定向到 walmart.com/blocked,说明你已经被识别出来了。麻烦之处在于,Walmart 经常会返回 200 状态码,但内容其实是 CAPTCHA 页面——所以只看 response.ok 完全不够。

如果是生产环境或重复调用,你几乎一定需要 住宅代理。数据中心 IP 会被 Akamai 的 IP 信誉系统快速封掉。后面的生产级错误处理和代理策略我会继续讲。

第 2 步:从 __NEXT_DATA__ JSON 中解析商品数据

Walmart.com 是一个 Next.js 应用,服务端渲染的 HTML 会把完整的 hydration payload 放进一个脚本标签里:<script id="__NEXT_DATA__" type="application/json">。这就是金矿。

:“到了 2026 年,Walmart 仍然使用 Next.js,并把结构化 JSON 放在 __NEXT_DATA__ script 标签里,因此提取隐藏数据比传统 CSS 选择器解析更可靠。” 几个高知名度的开源 Walmart 爬虫——包括 ——都在用这个方法。

提取方式如下:

1import json
2from parsel import Selector
3sel = Selector(text=response.text)
4raw = sel.xpath('//script[@id="__NEXT_DATA__"]/text()').get()
5data = json.loads(raw)
6product = data["props"]["pageProps"]["initialData"]["data"]["product"]
7idml = data["props"]["pageProps"]["initialData"]["data"].get("idml", {})

大多数教程写到这里就停了。下面是一个 完整的 JSON 路径对照表,对应你真正关心的字段——已基于 2024–2026 年的 Walmart 页面验证:

数据字段JSON 路径(在 initialData 下)类型说明
商品名称data > product > name字符串
品牌data > product > brand字符串
当前价格(数值)data > product > priceInfo > currentPrice > price浮点数可能因门店 cookie 不同而变化
当前价格(字符串)data > product > priceInfo > currentPrice > priceString字符串格式化结果,例如 "$9.99"
简短描述data > product > shortDescriptionHTML 字符串可用 BeautifulSoup 转成纯文本
长描述data > idml > longDescriptionHTML 字符串idml 上,不在 product——很多旧教程都会写错这里
全部图片data > product > imageInfo > allImages数组{id, url} 对象列表
平均评分data > product > averageRating浮点数键名是 averageRating,不是旧版的 rating
评论数data > product > numberOfReviews整数
变体data > product > variantCriteria数组选项组(尺寸、颜色)
可用性data > product > availabilityStatus字符串IN_STOCKOUT_OF_STOCKLIMITED_STOCK
卖家data > product > sellerDisplayName字符串
制造商data > product > manufacturerName字符串

longDescription 这条路径最容易踩坑。2023 年的 ScrapeHero 文章把它写在 product.longDescription,但 2024 年之后的资料基本都显示它在兄弟键 idml 里。务必先读 idml.longDescription,再在旧页面上回退到 product.longDescription

下面是使用 .get() 链式写法的安全提取模式:

1def extract_product(data):
2    product = data["props"]["pageProps"]["initialData"]["data"]["product"]
3    idml = data["props"]["pageProps"]["initialData"]["data"].get("idml", {})
4    price_info = product.get("priceInfo", {})
5    current_price = price_info.get("currentPrice", {})
6    image_info = product.get("imageInfo", {})
7    return {
8        "name": product.get("name"),
9        "brand": product.get("brand"),
10        "price": current_price.get("price"),
11        "price_string": current_price.get("priceString"),
12        "short_desc": product.get("shortDescription"),
13        "long_desc": idml.get("longDescription", product.get("longDescription")),
14        "images": [img.get("url") for img in image_info.get("allImages", [])],
15        "rating": product.get("averageRating"),
16        "review_count": product.get("numberOfReviews"),
17        "variants": product.get("variantCriteria"),
18        "availability": product.get("availabilityStatus"),
19        "seller": product.get("sellerDisplayName"),
20        "manufacturer": product.get("manufacturerName"),
21    }

如果你不想自己处理 JSON 路径, 会自动识别并结构化这些字段——你不需要手工映射路径。点击“AI Suggest Fields”,它会读取页面并输出表格。但如果你是在搭建自定义管线,上面的映射表就是你的参考。

第 3 步:拦截 Walmart 的内部 API,拿到更丰富的数据

没有一篇竞品文章把这部分讲清楚。它是最强的提取方式,也是最复杂的一种。

Walmart 前端调用的是基于 Apollo Gateway 的 。接口都挂在 www.walmart.com/orchestra/* 下面:

  • /orchestra/pdp/graphql — 商品详情 hydration + 变体切换
  • /orchestra/snb/graphql — 搜索与浏览分页
  • /orchestra/reviews/graphql — 分页评论

这些接口会返回干净、结构化的 JSON,其中有些数据是 __NEXT_DATA__ 会截断的——例如变体级价格、实时库存数量、完整的评论分页。

但这里有个很多博客都绕过去的坑: Walmart 使用的是 。请求体里只发送 SHA-256 hash(persistedQuery.sha256Hash),而不是完整查询文本。如果这个 hash 服务器不认识,你就会收到 PersistedQueryNotFound。Walmart 每次部署都会轮换这些 hash。这也是为什么那些高知名度的开源 Walmart 爬虫,几乎都不会直接发布可复制粘贴的 /orchestra/ 代码。

这个方法最现实的做法,是在 DevTools 里手动抓一遍:

  1. 在 Chrome 中打开一个 Walmart 商品页
  2. 打开 DevTools → Network 标签,筛选 “Fetch/XHR”
  3. 像正常用户一样浏览页面——点变体、滚动到评论、切换门店
  4. 找到返回商品数据的 /orchestra/* 请求
  5. 右键请求 → “Copy as cURL”
  6. curl_cffi 把 cURL 命令转换成 Python

下面是重放 API 请求的示例:

1import json
2from curl_cffi import requests
3session = requests.Session(impersonate="chrome124")
4# 先访问商品页,给会话预热
5session.get("https://www.walmart.com/ip/some-product/1234567", headers=HEADERS)
6# 然后重放内部 API 请求(从 DevTools 复制)
7api_url = "https://www.walmart.com/orchestra/pdp/graphql"
8api_headers = {
9    **HEADERS,
10    "accept": "application/json",
11    "content-type": "application/json",
12    "referer": "https://www.walmart.com/ip/some-product/1234567",
13    "wm_qos.correlation_id": "your-copied-correlation-id",
14}
15payload = {
16    # 把 DevTools 里的原始请求体粘贴进来
17    "variables": {"productId": "1234567"},
18    "extensions": {
19        "persistedQuery": {
20            "version": 1,
21            "sha256Hash": "the-hash-you-copied"
22        }
23    }
24}
25api_response = session.post(api_url, headers=api_headers, json=payload)
26api_data = api_response.json()

会话预热这一步非常关键。Walmart 的 PerimeterX cookie(_px3_pxhdACID)必须先由初始 HTML 请求写入,后面的 API 才能成功调用。没有这些 cookie,你通常会收到 412 或 403。

什么时候适合用这个方法: 当你需要 __NEXT_DATA__ 里没有的数据时,比如更深层的变体价格、超过第一页的分页评论,或者实时库存数。对大多数用途来说,__NEXT_DATA__ 已经足够,而且简单得多。

抓取 Walmart 搜索结果和多页内容

搜索结果也遵循类似的 __NEXT_DATA__ 结构,只是 JSON 路径不同:

1search_url = "https://www.walmart.com/search?q=laptops&page=1"
2response = session.get(search_url, headers=HEADERS)
3sel = Selector(text=response.text)
4raw = sel.xpath('//script[@id="__NEXT_DATA__"]/text()').get()
5data = json.loads(raw)
6search_result = data["props"]["pageProps"]["initialData"]["searchResult"]
7items = search_result["itemStacks"][0]["items"]
8# 过滤掉赞助商品
9organic_items = [i for i in items if i.get("__typename") == "Product"]
10for item in organic_items:
11    print(item.get("name"), item.get("priceInfo", {}).get("currentPrice", {}).get("price"))

分页通过递增 page 参数实现:&page=1&page=2,以此类推。但有个没有公开写明的限制:无论实际总页数是多少,Walmart 都把搜索结果最多限制为 25 页。 :“Walmart 设置了可访问结果页的最大数量为 25 页,不管总页数有多少。”

想拿到更深的覆盖范围,可以试这些办法:

  • 切换排序方式:同一个查询分别加 &sort=price_low&sort=price_high,大约能拿到 50 页覆盖
  • 按价格区间切片:加上 &min_price=X&max_price=Y,把目录切成更小的窗口
  • 按类目切片:在具体类目里搜索,而不是全站搜索

注意 itemStacks 是数组。Scrapfly 在仓库里直接硬编码了 [0],但类目页和浏览页有时会出现多个 stack(比如“热门推荐”“更多结果”)。更稳妥的做法是遍历所有 stack:

1for stack in search_result.get("itemStacks", []):
2    for item in stack.get("items", []):
3        if item.get("__typename") == "Product":
4            # 处理 item
5            pass

还有一点值得注意:Walmart 的 robots.txt 。商品详情页(/ip/...)和大多数类目页(/cp/...)并没有被禁止。如果你比较在意合规性,建议优先从商品页和类目树开始,而不是搜索页。

不要让静默封锁毁掉你的数据:生产级错误处理

大多数教程都会在这里翻车。它们只教你抓一页、解析一个商品、然后就结束了。但在生产环境里,你会抓成千上万的页面,而 Walmart 也一直在想办法拦你。一个 demo 爬虫和一个真正能用的爬虫,差别就在于你怎么处理失败。

在数据被污染前识别静默封锁

Walmart 爬虫里最重要的函数,就是封锁检测器。根据 的一致经验,你需要四个独立检查:

1BLOCK_MARKERS = (
2    "Robot or human",
3    "Press &amp; Hold",
4    "Press & Hold",
5    "px-captcha",
6    "perimeterx",
7)
8def is_walmart_blocked(response) -> bool:
9    # 1. 重定向到专门的封锁页面
10    if "/blocked" in str(response.url):
11        return True
12    # 2. 明确的状态码
13    if response.status_code in (403, 412, 428, 429, 503):
14        return True
15    # 3. 200 OK 但正文是 CAPTCHA(静默封锁)
16    body = response.text or ""
17    if any(m.lower() in body.lower() for m in BLOCK_MARKERS):
18        return True
19    # 4. 响应长度检查——真实 PDP 通常是 300–900 KB
20    if len(response.content) &lt; 50_000 and "/ip/" in str(response.url):
21        return True
22    return False

第四个检查——响应长度——可以抓住那些没有明显 CAPTCHA 标记,但也没有任何商品数据的“简化页面”。

带指数退避和抖动的重试逻辑

请求失败时,别马上猛刷 Walmart。标准做法是指数退避加抖动,避免重试节奏完全同步:

1import time
2import random
3import logging
4from curl_cffi import requests as cffi_requests
5log = logging.getLogger("walmart")
6def fetch_with_retry(session, url, max_retries=5, base_delay=2, max_delay=60):
7    for attempt in range(max_retries):
8        try:
9            response = session.get(url, headers=HEADERS, timeout=15)
10            if response.status_code in (429, 503):
11                raise Exception(f"Throttled: {response.status_code}")
12            if is_walmart_blocked(response):
13                raise Exception("Silent block detected")
14            return response
15        except Exception as e:
16            if attempt == max_retries - 1:
17                raise
18            wait = min(max_delay, base_delay * (2 ** attempt)) + random.uniform(0, 3)
19            log.warning(f"Attempt {attempt + 1} failed: {e}. Retrying in {wait:.1f}s")
20            time.sleep(wait)
21    return None

这里的抖动(random.uniform(0, 3))不是装饰,它能让多个爬虫实例不会在同一秒同时重试,从而触发 Akamai 的速度检测。

速率限制

都建议 Walmart 采用 每次请求随机等待 3–6 秒:“把页面加载间隔控制在 3–6 秒之间,并且随机化延迟。”

1import time
2import random
3def rate_limited_fetch(session, url):
4    response = fetch_with_retry(session, url)
5    time.sleep(random.uniform(3.0, 6.0))
6    return response

如果规模更大,可以用 aiolimiter 做异步限速:

1from aiolimiter import AsyncLimiter
2limiter = AsyncLimiter(max_rate=10, time_period=60)  # 每分钟 10 个请求

数据验证

即使响应没有被封,解析出来的数据也可能是错的(门店不对、负载被降级)。在写入输出前先做校验:

1def validate_product(product):
2    """如果商品数据看起来合理,则返回 True。"""
3    if not product.get("name"):
4        return False
5    price = (product.get("priceInfo") or {}).get("currentPrice", {}).get("price")
6    if not isinstance(price, (int, float)) or price &lt;= 0:
7        return False
8    if product.get("availabilityStatus") not in ("IN_STOCK", "OUT_OF_STOCK", "LIMITED_STOCK"):
9        return False
10    return True

会话日志记录

跟踪每个会话的成功率。当 10 分钟内成功率跌到 80% 以下时,说明情况变了——可能是 IP 被封了、cookie 过期了,或者 Walmart 上了新的反爬规则。

1class ScrapeMetrics:
2    def __init__(self):
3        self.total = 0
4        self.success = 0
5        self.blocks = 0
6        self.errors = 0
7    def record(self, result):
8        self.total += 1
9        if result == "success":
10            self.success += 1
11        elif result == "blocked":
12            self.blocks += 1
13        else:
14            self.errors += 1
15    @property
16    def success_rate(self):
17        return (self.success / self.total * 100) if self.total &gt; 0 else 0
18    def check_health(self):
19        if self.total &gt; 20 and self.success_rate &lt; 80:
20            log.critical(f"Success rate dropped to {self.success_rate:.1f}% — consider rotating proxies or pausing")

不花哨,但它能保证你的数据干净。

自己写 Python vs. 抓取 API vs. 无代码:如何选择抓取 Walmart 的方式

很多开发者一上来就想自己写爬虫,却没先判断这是不是最合适的方案。。论坛用户也常说它“基本就是 9/10”,并纠结“专门买一个网页抓取 API 会不会太重了”。答案取决于抓取量、预算和工程能力。

因素自建 Python(requests + 代理)抓取 API(Oxylabs、Bright Data 等)无代码工具 (Thunderbit)
初次出数据的配置时间几小时15–60 分钟约 2 分钟
上线到可生产使用40–80 小时4–16 小时约 30 分钟
反爬处理你自己负责(很难)服务商负责自动处理
小规模成本(<1K 页/月)低(代理约 $4–8/GB)$40–$49/月起免费–$15/月
大规模成本(10 万+ 页/月)单次成本更低单次成本更高视情况而定
定制能力完全可控受 API 参数限制受 UI/字段限制
持续维护每月 4–8 小时几乎为零无需维护(AI 自适应)
最适合需要自定义管线的开发者中等规模生产抓取商业用户、临时快速提取

什么时候适合自己写 Python

如果你已经有代理合同、需要严格控制请求头、邮编定位或卖家群组,或者你每月要索引数百万页面、API 单条费用累积起来很高,又或者你需要本地部署或合规保证,那么自建方案更划算。代价也很现实:一个可投入生产的 Scrapy 爬虫,支持分页、重试、代理轮换、TLS 模拟和多页面类型 schema,通常需要 ,之后每月还要花 4–8 小时维护,因为 Walmart 会不断轮换指纹。

什么时候抓取 API 更省时间

抓取 API 会帮你处理反爬层,这样你就不用自己折腾了。 显示 Walmart 上 ,而 Scrape.do 成功率 98%。像 这样的工具,入门价大概在每月 $40–$49。若你是 2–5 人的小团队,每月抓取量在 1 万到 100 万页之间,API 基本上总是更合适。你用每次请求的费用,换来几乎零维护。

什么时候无代码才是正确答案

适合完全不同的人群。如果你是 PM、分析师或电商运营,希望今天下午就把 Walmart 数据放进表格里,而不是等到下个迭代,那无代码工具就是最诚实的答案。

流程很简单:安装 ,打开 Walmart 商品页或搜索页,点击“AI Suggest Fields”,Thunderbit 的 AI 会读取页面并推荐字段列(商品名、价格、评分等)。再点“Scrape”,数据就会进入表格。然后可以免费导出到 Excel、Google Sheets、Airtable 或 Notion。

Thunderbit 把反爬处理放在云端,所以你不需要面对 CAPTCHA、代理和 TLS 指纹这些麻烦。AI 也会自动适应页面布局变化,因此几乎不需要维护。对于不想碰 JSON 路径的人来说,这基本就是阻力最小的路径。

但也要诚实地说限制:Thunderbit 不是为每天 10 万+ 页面设计的。积分预算和云端上限会让超大规模采集的成本高于原生 API。你也无法在工具不支持的情况下固定某个邮编或 ASN。对于持续、超高频的数据管道,DIY 或抓取 API 仍然更合适。

粗略价格估算: 在 Thunderbit 上抓取 1000 条 Walmart 商品数据,大约消耗 2000 积分(Starter/Pro 方案约 $0.60–$1.10)。这和 Oxylabs 的 Walmart API 差不多,在低量场景下还比大多数入门级抓取 API 更便宜。具体价格请查看

导出你抓取到的 Walmart 数据

拿到数据后,你得把它放到真正能用的地方。下面三种格式已经能覆盖大多数需求:

CSV —— 分析师最常打开的通用格式:

1import csv
2def export_csv(products, filename="walmart_products.csv"):
3    fieldnames = ["name", "price", "availability", "rating", "review_count", "seller", "url"]
4    with open(filename, "w", newline="", encoding="utf-8-sig") as f:
5        writer = csv.DictWriter(f, fieldnames=fieldnames, quoting=csv.QUOTE_MINIMAL)
6        writer.writeheader()
7        for p in products:
8            writer.writerow({k: p.get(k) for k in fieldnames})

这里使用 utf-8-sig 编码是为了兼容 Excel。BOM 标记可以避免 Excel 把特殊字符弄乱。

JSONL —— 适合生产级抓取管线的格式:

1import json
2import gzip
3def export_jsonl(products, filename="walmart_products.jsonl.gz"):
4    with gzip.open(filename, "at", encoding="utf-8") as f:
5        for p in products:
6            f.write(json.dumps(p, ensure_ascii=False) + "\n")

(中断写入通常只丢最后一行),可以流式写入、常量内存运行,并保留变体、评论这类嵌套数据。

Excel —— 适合一次性给分析师交接:

1from openpyxl import Workbook
2def export_excel(products, filename="walmart_products.xlsx"):
3    wb = Workbook(write_only=True)
4    ws = wb.create_sheet("Products")
5    ws.append(["Name", "Price", "Availability", "Rating", "Reviews", "Seller"])
6    for p in products:
7        ws.append([p.get("name"), p.get("price"), p.get("availability"),
8                    p.get("rating"), p.get("review_count"), p.get("seller")])
9    wb.save(filename)

对于非 Python 用户,Thunderbit 也覆盖了导出:一键导出到 Google Sheets、Airtable、Notion、Excel、CSV 和 JSON——基础版全部免费。对于持续监控,Thunderbit 的定时爬虫功能还能自动执行重复抓取。

关于定时抓取还有一个注意事项:。GitHub Actions 的运行器使用的是 Azure IP 段,而 Walmart 的反爬会直接封掉这些 IP。建议在 VPS 上用 APScheduler,或者把所有流量都走住宅代理。

抓取 Walmart 的法律与伦理指南

论坛用户会很直接地表达这种担忧:“我不介意和工程团队玩猫鼠游戏,但我不想和他们的法务团队过招。”

Walmart 的使用条款 在没有“事先书面同意”的情况下,使用“任何机器人、蜘蛛……或其他手动或自动设备来检索、索引、‘scrape’、‘data mine’ 或以其他方式收集任何材料”。

Walmart 的 robots.txt /search/account/api/ 以及大量内部接口。但商品详情页(/ip/...)和评论页(/reviews/product/)并未被禁止。

hiQ v. LinkedIn 判例(第九巡回法院,)确立了一个原则:抓取公开可访问的数据,通常不太可能违反联邦 CFAA。不过,同一法院后来又裁定 ,并对其作出 。更近的 2024 年判决()进一步缩小了 CFAA 的适用范围,并带来了版权优先适用抗辩;但这些裁定依赖于特定的 ToU 文本,不能直接照搬到 Walmart 上。

实用建议: 不要压垮服务器。尊重速率限制。不要抓取个人数据或用户数据。负责任地使用数据。以适中的速率抓取公开 Walmart 商品页用于个人研究,和以商业规模抓取并违反 Walmart 条款,是两种完全不同的风险画像。如果你打算基于 Walmart 数据做产品,最好先咨询律师,并看看 Walmart 官方的

免责声明: 以上内容仅用于教育目的,不构成法律建议。

结论与核心要点

由于 Walmart 同时使用 Akamai + PerimeterX 双层反爬,使用 Python 抓取它是一个 。不是不可能,但你必须使用正确的工具和方法。

核心要点:

  • __NEXT_DATA__ JSON 提取是大多数场景下最务实的方案。 这也是 2024–2026 年几乎所有严肃开源 Walmart 爬虫的做法。PDP 的基础路径是 props.pageProps.initialData.data.product,搜索/浏览页则是 searchResult.itemStacks
  • curl_cffi 配合 impersonate="chrome124" 是必须的。 仅靠 requestshttpx,无论怎么改请求头,都过不了 Akamai 的 TLS 指纹识别。
  • 静默封锁才是真正危险的地方。 Walmart 会返回带 CAPTCHA 内容的 200 OK。要检查响应正文,不要只看状态码。
  • 生产级爬虫需要的不只是 happy path 代码。 指数退避加抖动、四信号封锁检测、每次请求 3–6 秒速率限制、数据验证和会话健康监控,都是必需的。
  • 通过 /orchestra/* 拦截内部 API 很强,但也很脆弱。 把它当成针对特定数据需求的 DevTools 练习,而不是主提取方式。
  • Walmart 把搜索结果限制在 25 页。 想拿更多覆盖,可以通过切换排序和按价格区间切片来扩大范围。
  • 诚实选择适合自己的方案: 如果你是开发者、需要定制流程、而且量大,就用 DIY Python;如果你是中等规模团队、又没有专门的抓取工程师,就用抓取 API;如果你是想今天下午就把数据放进 Google Sheets 的业务人员,就用

如果你想试试无代码路线, 有免费额度——你可以先抓几页 Walmart 数据,亲眼看看结果。如果你决定走 Python 路线,这篇文章里的代码模式已经在生产环境里验证过了。无论哪条路,现在你都已经掌握了 Walmart 的防线图,以及穿过它们的三种方式。

想了解更多网页抓取技巧,可以查看我们关于 的指南。你也可以在 看教程。

常见问题

用 Python 抓取 Walmart 商品数据合法吗?

Walmart 的使用条款禁止在未经书面同意的情况下进行自动抓取。第九巡回法院在 hiQ v. LinkedIn(2022)一案中判定,联邦 CFAA 很可能不适用于抓取公开页面,但同案最终还是以抓取方违反合同并被判赔 收场。以较低频率抓取公开商品页用于个人研究,和商业规模抓取,风险画像完全不同。如果你打算围绕 Walmart 数据做生意,务必先咨询律师。

为什么我的 Walmart 爬虫总是被封?

最常见的原因有:使用普通 requestshttpx(它们会发出 Python 特征的 TLS 指纹,Akamai 会立刻识别)、请求头缺失或错误、没有代理轮换、请求速度快于每页 3–6 秒,以及缺少会话 cookie(_px3_abcklocDataV3)。请改用带 impersonate="chrome124"curl_cffi,使用住宅代理,并按本文所述实现封锁检测和重试逻辑。

用 Python 可以从 Walmart 抓到哪些数据?

商品名称、价格(当前价和回滚价)、图片、简短和长描述、评分、评论数、库存状态、卖家名称、制造商信息、变体选项(尺寸、颜色)以及类目归属。使用 __NEXT_DATA__ 方法时,这些数据都以结构化 JSON 形式提供。内部 API 拦截还能额外拿到变体级价格、实时库存数量和分页评论数据。

抓取 Walmart 需要代理吗?

需要,凡是生产环境或重复使用都需要。——即使请求头完全正确,非住宅 IP 也会被 Akamai 的 IP 信誉系统标记。住宅代理或移动代理是必须的。数据中心 IP 几乎会立刻失效。按代理服务商和套餐不同,每 1000 页大约预算 $3–$17。

不写代码也能抓 Walmart 吗?

可以。 是一款 AI 驱动的 Chrome 扩展,只需两步就能抓 Walmart:“AI Suggest Fields” 自动识别商品数据列,然后点“Scrape”导出数据。它会在云端处理反爬挑战,并可直接导出到 Excel、Google Sheets、Airtable 或 Notion,而且全部免费。它最适合分析师、PM 和需要快速拿数据的业务人员,不需要自己搭建自定义管线。若是高频或高度定制化抓取,Python 或抓取 API 仍然更合适。

试试 Thunderbit 的 AI Walmart 抓取

了解更多

Shuai Guan
Shuai Guan
Co-founder/CEO @ Thunderbit. Passionate about cross section of AI and Automation. He's a big advocate of automation and loves making it more accessible to everyone. Beyond tech, he channels his creativity through a passion for photography, capturing stories one picture at a time.
目录

试试 Thunderbit

只需 2 次点击即可抓取线索和其他数据。AI 驱动。

获取 Thunderbit 免费使用
使用 AI 提取数据
轻松将数据传输到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week