Walmart 拥有互联网上规模最大的零售商品目录之一,其中绝大部分内容对外公开:搜索结果、商品详情页、用户评论、畅销商品排名,以及散布在搜索结果和分类页面中的赞助位。这些数据被用于价格追踪、竞品调研、品类分析和需求预测,这也正是开发者不断尝试获取它们的原因。难点在于如何干净地提取这些数据,因为 Walmart 大部分页面内容都在浏览器端渲染,并且对自动化流量的识别和拦截非常严格。
本指南是整个 Walmart 系列的路线图。它梳理了可抓取的数据入口,解释了为什么普通 HTTP 请求几乎返回空页面,并提供了一个完整的端到端可运行示例:使用 JavaScript 和 Node.js 编写的 Walmart 搜索结果页抓取脚本,通过 Crawling API 获取页面,再用 cheerio 将结果解析为结构化 JSON。本指南仅涵盖公开商品数据,并指引你前往各专题指南深入了解价格、评论、畅销榜和广告,最后还会客观地介绍法律层面的注意事项。在大规模使用之前,请务必阅读该部分。
可抓取的 Walmart 数据入口
在写任何代码之前,先了解哪些数据实际可以获取是很有帮助的。Walmart 提供了若干不同的公开数据入口,每个入口都是独立的抓取任务,有各自的页面结构和选择器。可以把这些入口当作整个系列的地图:
- 搜索结果(SERP):输入搜索词(如"iphone 14 pro")后得到的列表视图。每个卡片包含商品名称、价格、评分、评论数、配送信息以及赞助标记。这是下文的运行示例,更详细的说明见 使用 Python 抓取 Walmart 搜索结果。
- 商品页面:单个商品的完整详情页,包含详细描述、规格参数、所有图片、卖家信息和实时价格。专题指南见 使用 Selenium 抓取 Walmart 商品页面。
- 价格:大多数团队最常需要定期获取的单一字段,用于竞品监控和动态定价。参见 如何轻松抓取 Walmart 价格。
- 评论:商品页面上的公开评分分布和单条评论文本,可用于情感分析和质量信号提取。参见 Walmart 评论抓取指南。
- 畅销商品:Walmart 的分类排行榜,可快速了解热销商品。参见 抓取 Walmart 畅销商品。
- 赞助广告:搜索结果和分类页面中的付费推广位,适合用于广告情报分析。参见 Walmart 赞助广告抓取。
所有入口的技术路径相同:先渲染页面,再用 CSS 选择器解析目标字段。本文以搜索结果为例,因为搜索卡片几乎涵盖了 Walmart 的所有字段类型,一旦能解析 SERP 卡片,其他入口也就触类旁通了。
要构建的内容
一个 Node.js 脚本,接收一个公开的 Walmart 搜索 URL,通过 Crawling API 获取渲染后的 HTML,并从结果页面中为每个商品提取结构化记录。我们以搜索词"iphone 14 pro"为示例,每条记录包含以下字段:
- 商品名称(Title):例如"Straight Talk Apple iPhone 14 Pro Max, 128GB, Silver"。
- 价格(Price):页面显示的价格,如"1,099"。
- 货币符号(Currency):如"$"。
- 评分(Review star):评分字符串,如"4.4 out of 5 Stars. 31 reviews"。
- 评论数(Reviews count):卡片上显示的评论数量。
- 配送信息(Delivery message):如"Free shipping, arrives in 3+ days"。
- 商品徽章(Product badge):卡片上的标签,如"Popular pick"(若有)。
- 库存状态(Inventory status):"In Stock"或"Out of stock"。
- 是否赞助(Is sponsored):标识是否为付费推广的布尔值。
- 图片(Image):商品缩略图 URL。
为什么普通请求在 Walmart 上会失败
如果你用普通的 HTTP 客户端请求 Walmart 搜索 URL,返回的响应几乎缺少你所需要的所有内容。有两个原因在阻碍你。首先,Walmart 通过 JavaScript 在浏览器端渲染价格、评分、配送信息和大部分卡片详情,因此在页面脚本执行之前,初始 HTML 只是一个空壳。其次,Walmart 很快就会识别出自动化流量:数据中心 IP 以及与真实浏览器不符的请求模式,会在接触到渲染内容之前就被拦截、限速或封禁。
因此,一个可用的 Walmart 爬虫需要在单次请求中同时满足两点:能真正渲染页面的浏览器,以及被平台识别为真实访客的 IP。你可以自行搭建无头浏览器和轮换住宅代理池,但将两者整合并持续维护是绝大部分的工作量。Crawling API 将两者合并为一次调用:你发送 URL,它在可信 IP 后渲染页面,然后返回完整 HTML 供你解析。如果你只是想了解代理选择这一权衡,可以参阅 Walmart 爬取代理基准测试,其中有更深入的分析。
Crawlbase 提供两种 token 类型。普通 token 获取静态 HTML;JavaScript token 则会先在真实浏览器中渲染页面。Walmart 的关键卡片字段是客户端加载的,因此 JavaScript token 能返回最完整的页面。普通 token 可能返回缺少价格或评分的不完整结果,让你无法可靠地解析。JavaScript 请求消耗更多积分,因此应在页面确实需要渲染时才使用。
前提条件
在编写代码之前,你需要准备好以下几样东西,都不需要太多时间。
基本的 JavaScript 和 Node.js 知识。你应当能够编写并运行 Node 脚本,并使用 npm 安装包。如果你刚接触 Node.js,官方文档和任何入门课程都能让你达到本教程所需的水平。更完整的指南可参考我们的 使用 Node.js 构建 Web 爬虫。
Node.js 16 或更高版本。用 node --version 确认你的版本。如果尚未安装,可从 Node.js 官网或 nvm 等版本管理器获取。
Crawlbase 账号和 token。注册账号,打开控制台,从账号文档页面复制你的 token。注册即可获得 1,000 次免费请求,无需绑定信用卡,完全足够完成本项目。请像对待密码一样保管 token:它用于验证你的请求,不要将其纳入版本控制。
初始化项目
创建项目文件夹,初始化项目,并安装爬虫所需的两个库。
node --version mkdir walmart-scraper && cd walmart-scraper npm init -y npm install crawlbase cheerio
两个依赖各司其职:crawlbase 是 Crawling API 的官方 Node 客户端,cheerio 使用类 jQuery 的 API 解析返回的 HTML,从而通过 CSS 选择器提取各字段。如果你对选择器还不熟悉,XPath 与 CSS 选择器入门 是一个很好的补充参考。该项目的旧版本还使用 Express 暴露了一个 /scrape 端点,如果你想通过 HTTP 调用爬虫,这是一种不错的模式,但它是可选的,本文的核心脚本保持独立。
步骤 1:获取渲染后的搜索页面
首先获取完整页面。导入 CrawlingAPI 类,用你的 token 初始化,然后请求搜索 URL。在解析之前先检查状态码,可以让错误更明显而不是悄然失败。
const { CrawlingAPI } = require('crawlbase'); const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' }); async function crawl(pageUrl) { const response = await api.get(pageUrl); if (response.statusCode === 200) { return response.body; } console.error(`Request failed: ${response.statusCode}`); return null; } const searchUrl = 'https://www.walmart.com/search?q=iphone+14+pro'; crawl(searchUrl).then((html) => { console.log(html ? html.slice(0, 500) : 'No HTML returned'); });
用 node scraper.js 运行脚本,你应该能看到真实的 Walmart 标记,而不是精简后的空壳。这表明渲染和 IP 轮换在你编写任何选择器之前就已经正常工作了。如果响应体很小,说明该页面需要 JavaScript 请求:切换到你的 JavaScript token,它会在返回 HTML 之前在真实浏览器中渲染页面。
这次调用刚刚在可信 IP 后渲染了一个 Walmart 搜索页面,你无需碰任何浏览器或代理。Crawling API 在真实浏览器中运行页面,在服务器端轮换住宅 IP,然后返回完整 HTML,这样你就不必自己运行无头浏览器集群和代理池。先在免费额度内用它来请求一个公开搜索页面。
步骤 2:用 cheerio 解析每个商品
拿到渲染后的 HTML,将其加载到 cheerio 并遍历结果卡片。Walmart 将每条搜索结果排列在重复的列表视图块中,所以你先选取所有卡片,再从内部读取各字段。以下选择器直接来自真实 Walmart SERP。防御性地读取每个字段,可以避免某个字段缺失导致整个运行崩溃。
const cheerio = require('cheerio'); function parseProductsFromHTML(html) { const $ = cheerio.load(html); const products = []; $('div[role="group"] div[data-testid="list-view"]').each((_, element) => { const el = $(element); const title = el.find('[data-automation-id="product-title"]').text(); if (!title) return; products.push({ title, image: el.find('[data-testid="productTileImage"]').attr('src'), price: el.find('[data-automation-id="product-price"] .lh-copy span.f2').text(), currency: el.find('[data-automation-id="product-price"] .f6.f5-l:first').text(), reviewsCount: el.find('[aria-hidden=true].f7').text(), reviewStar: el.find('.flex.items-center.mt2 .w_iUH7').text(), deliveryMessage: el.find('[data-automation-id="fulfillment-badge"]').text().trim(), productBadge: el.find('.tag-leading-badge').text(), inventoryStatus: el.find('[data-automation-id="inventory-status"]').text() || 'In Stock', isSponsored: el.find('.lh-title > .gray.f7').text() ? true : false, }); }); return { products, productsCount: products.length }; }
这段代码遍历页面上的所有列表视图卡片,并通过选择器读取每个字段:title、image、price、currency、reviewsCount、reviewStar、deliveryMessage、productBadge、inventoryStatus 以及 isSponsored 标志。当没有缺货标记时,库存状态默认为"In Stock";isSponsored 通过检测卡片内的小赞助标签来解析为布尔值。同一个循环也可以用来隔离付费推广位,进行广告情报分析,因为赞助标志已经包含在记录中了。
Walmart 的类名和 data-testid 标记会不定期更新,并且在搜索、商品和分类页面之间也存在差异。把上面的选择器当作起始模板,而非固定规范。当某个字段返回空值时,在浏览器开发者工具中重新检查实时页面并更新选择器。定期维护选择器是任何生产级爬虫的正常工作,并非出了什么问题。
步骤 3:整合代码
现在将获取和解析步骤整合成一个可运行的脚本。获取渲染后的 HTML,传入解析器,然后将结构化记录以 JSON 格式打印出来。
const { CrawlingAPI } = require('crawlbase'); const cheerio = require('cheerio'); const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' }); async function crawl(pageUrl) { const response = await api.get(pageUrl); if (response.statusCode === 200) return response.body; console.error(`Request failed: ${response.statusCode}`); return null; } function parseProductsFromHTML(html) { const $ = cheerio.load(html); const products = []; $('div[role="group"] div[data-testid="list-view"]').each((_, element) => { const el = $(element); const title = el.find('[data-automation-id="product-title"]').text(); if (!title) return; products.push({ title, image: el.find('[data-testid="productTileImage"]').attr('src'), price: el.find('[data-automation-id="product-price"] .lh-copy span.f2').text(), currency: el.find('[data-automation-id="product-price"] .f6.f5-l:first').text(), reviewsCount: el.find('[aria-hidden=true].f7').text(), reviewStar: el.find('.flex.items-center.mt2 .w_iUH7').text(), deliveryMessage: el.find('[data-automation-id="fulfillment-badge"]').text().trim(), productBadge: el.find('.tag-leading-badge').text(), inventoryStatus: el.find('[data-automation-id="inventory-status"]').text() || 'In Stock', isSponsored: el.find('.lh-title > .gray.f7').text() ? true : false, }); }); return { products, productsCount: products.length }; } async function main() { const searchUrl = 'https://www.walmart.com/search?q=iphone+14+pro'; const html = await crawl(searchUrl); if (!html) return; const data = parseProductsFromHTML(html); console.log(JSON.stringify(data, null, 2)); } main();
提供 URL 后,脚本通过 Crawling API 渲染页面,解析每个商品卡片,并返回一个包含商品列表和数量的干净对象。这就是从 URL 到结构化数据的完整流程,全部在一个文件中完成。
输出结果示例
用 node scraper.js 运行完整脚本,你会得到一个干净的对象:一个 products 数组,每个卡片对应一条记录,加上 productsCount。它可以直接写入 JSON、CSV 或数据库。
{ "products": [ { "title": "Straight Talk Apple iPhone 14 Pro Max, 128GB, Silver- Prepaid Smartphone", "image": "https://i5.walmartimages.com/seo/Straight-Talk-Apple-iPhone-14-Pro-Max.jpeg", "price": "1,099", "currency": "$", "reviewsCount": "31", "reviewStar": "4.4 out of 5 Stars. 31 reviews", "deliveryMessage": "Free shipping, arrives in 3+ days", "productBadge": "Popular pick", "inventoryStatus": "In Stock", "isSponsored": true }, { "title": "Restored Apple iPhone 14 Pro 128GB Deep Purple (Unlocked) Used Excellent", "image": "https://i5.walmartimages.com/asr/1385d15c-17b0-4392-8fc1-414cae1a51ed.jpeg", "price": "899", "currency": "$", "reviewsCount": "5", "reviewStar": "4.2 out of 5 Stars. 5 reviews", "deliveryMessage": "Free shipping, arrives in 3+ days", "productBadge": "", "inventoryStatus": "In Stock", "isSponsored": false } ], "productsCount": 2 }
跨结果页扩展爬取
爬取一页结果只是演示;真实任务需要遍历分页。Walmart 在搜索 URL 中使用 page 参数,因此你可以在循环中构建每页 URL,通过 Crawling API 获取,用同一个函数解析,并收集所有数据行。典型序列如下:
https://www.walmart.com/search?q=iphone+14+prohttps://www.walmart.com/search?q=iphone+14+pro&page=2https://www.walmart.com/search?q=iphone+14+pro&page=3
async function scrapePages(query, totalPages) { const all = []; for (let page = 1; page <= totalPages; page++) { const url = `https://www.walmart.com/search?q=${encodeURIComponent(query)}&page=${page}`; const html = await crawl(url); if (html) all.push(...parseProductsFromHTML(html).products); } return all; } scrapePages('iphone 14 pro', 3).then((rows) => { console.log(`Collected ${rows.length} products`); });
从这里开始,你可以扩展到数千个搜索页面,并将输出存储到数据库或云端。如果想为每条记录补充完整详情(长描述、所有图片、完整评论分布),可以取商品链接,通过同一个 crawl 函数获取该商品详情页,然后为商品页面布局编写小型解析器。模式完全相同:渲染,再解析。商品页面指南和评论指南正是从这里接续展开的。
保持不被封禁
即使处理好了渲染问题,Walmart 仍然会监控爬虫特征的流量。如果没有大规模轮换 IP 池,被封禁的风险是真实存在的,而自建 IP 池既耗时又昂贵。以下几个习惯可以让一次爬取任务保持健康,它们适用于任何强防护的商业目标站点。
- 控制请求节奏。在紧密循环中大量请求是最快触发限速的方式。适当分散请求并变换查询词,而不是以最高速度爬取同一路径。
- 依赖 IP 轮换。住宅 IP 池将请求分散到众多真实用户地址,使单个地址不会触发速率限制。Crawling API 已为你处理好了这一点;如果你自行搭建,这一环节是最关键的。
- 关注状态码。当一次运行开始返回验证挑战或错误时,这说明当前的请求频率或 IP 层级已不够用。把它当作信号来降速,而不是当作噪音来忽略。
关于更全面的策略,参见 如何不被封禁地抓取网站。如果你希望通过自己的流量路由替代托管 API,Smart AI Proxy 提供与 Crawling API 相同的住宅 IP 轮换作为直接可用的端点。Walmart 也是 电商网页抓取中的常见目标,相同的渲染后解析模式可跨站复用,所得价格数据直接适用于 价格情报分析工作。
抓取 Walmart 数据合法吗?
是否允许抓取 Walmart 数据,取决于 Walmart 的服务条款、你所在的司法管辖区,以及你如何使用这些数据。Walmart 的条款限制自动化访问,因此无论你的工具多么谨慎,抓取行为都可能违反这些条款。本文中的任何代码都不会改变这一点,它只是让技术层面的工作可行。请阅读 Walmart 的使用条款及其 robots.txt,并将二者视为你采集内容的边界。
有几条原则值得坚守。仅采集公开商品数据:任何人无需账号即可看到的商品名称、价格、评分、评论数、配送信息、徽章、库存状态和赞助标记。遵守 Walmart 的合理速率预期,将请求量控制在不给其服务器造成压力的范围内。避免个人数据,包括任何超出公开评论文本本身、与可识别评论者相关联的内容,并且不要以图片版权所有者的名义再分发商品图片等受版权保护的媒体资源。
对于大规模或商业用途,请优先使用官方渠道。Walmart 有开发者平台以及联盟和市场 API,当你需要大量数据、有保障的结构或商业权利时,这些才是正确的工具。本指南刻意将范围限定在公开搜索和商品页面,因为这条线让工作处于可辩护的范围内。它不涵盖任何登录后的内容、客户或卖家账号数据、订单历史、私信,以及任何绕过身份验证的尝试。如果你的项目需要超出公开商品列表的内容,Walmart 的官方 API 或数据协议才是正确路径,而不是更聪明的爬虫。
核心要点
- Walmart 有多个公开数据入口。搜索、商品页面、价格、评论、畅销榜和赞助广告,解析方式相同,先渲染再用选择器读取字段,每个入口在该系列中都有专属深度指南。
- 普通请求只能获取空壳。Walmart 在客户端渲染卡片内容并拦截机器人流量,因此必须在可信 IP 后渲染页面才能解析数据。
- Crawling API 一次调用完成两件事。它在服务器端渲染页面并轮换住宅 IP,因此你无需自行运行无头浏览器集群和代理池;JavaScript 请求消耗更多积分,请在页面确实需要时才使用。
- cheerio 负责提取数据。选取每个列表视图卡片,然后将商品名称、价格、货币、评分、配送信息、徽章、库存状态和赞助标记映射到当前选择器,并预期这些选择器会发生变化。
- 坚守公开数据边界。遵守 Walmart 的服务条款和 robots.txt,控制请求节奏,大规模或商业使用时优先选择官方 API,绝对不要涉及登录内容、账号数据或个人信息。
常见问题
为什么普通请求从 Walmart 返回的数据不完整?
因为 Walmart 使用 JavaScript 在客户端渲染价格、评分、配送信息和大部分卡片详情。在浏览器运行页面脚本之前,初始 HTML 只是一个空壳,因此原始 HTTP 请求会返回关键字段缺失或空白的页面。要获取完整页面,必须先进行渲染,这正是 Crawling API 所处理的工作;而 JavaScript token 会在页面需要时强制执行完整的浏览器渲染。
对于 Walmart,我应该使用普通 token 还是 JavaScript token?
先使用普通 token 并检查响应体。如果价格、评分或其他卡片字段返回空值,则切换到 JavaScript token,它会在返回 HTML 之前在真实浏览器中渲染页面。JavaScript 请求消耗更多积分,因此在普通 token 够用的地方使用普通 token,仅将 JavaScript token 用于确实需要渲染的页面。
如何抓取 Walmart 搜索结果的下一页?
Walmart 在搜索 URL 中使用 page 参数,因此追加 &page=2、&page=3 等即可翻页浏览结果。在循环中构建每页 URL,通过 Crawling API 获取,再对每页运行同一个解析器。由于每页结果共享相同的卡片结构,你已有的解析器无需修改即可适用于所有页面。
我的选择器返回空字符串,是什么变了?
几乎可以肯定是 Walmart 修改了标记。其类名和 data-testid 标记会不定期更改,在搜索、商品和分类页面之间也存在差异,因此上个月还能用的选择器可能已经失效。在浏览器开发者工具中重新检查实时页面并更新选择器。对于任何生产级爬虫来说,定期维护选择器是正常工作。
我可以抓取 Walmart 上客户或卖家的个人数据吗?
不可以,本指南也不涵盖这些内容。账号详情、订单历史和私信都在登录后才能访问,属于非公开数据。商品页面上的公开评论文本是可见的,但仍应避免将其与可识别的个人关联起来。抓取登录后内容、个人数据,或绕过身份验证来获取这些内容,超出了本指南的范围,且违反了 Walmart 的服务条款。
价格、评论、畅销榜或广告该去哪里继续学习?
本路线图端到端地涵盖了搜索结果;整个系列对每个数据入口都有专属指南。参见 抓取 Walmart 价格、评论抓取指南、畅销商品和 赞助广告。每个指南都在不同的 Walmart 页面上使用相同的渲染后解析方法。
大规模爬取任何站点,无需与基础设施对抗。
Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

