Walmart 的畅销榜按部门对销售最快的商品进行排名,从电子产品到家居用品,这份公开排名是开放网络上最清晰的需求信号之一。零售商借此了解趋势走向,分析师用它研究类别变化,价格追踪器将其作为当前热销商品比较的基准。数据就摆在页面上:排名顺序、商品标题、价格、评分,以及指向每件商品的链接。

本指南介绍如何使用 JavaScript 和 Node.js,结合 cheerio,抓取 Walmart 畅销榜。你将构建一个小型可运行的爬虫,通过 Crawling API 获取 Walmart 畅销榜页面,解析每件商品的排名、标题、价格、评分和链接,并将结果导出为 JSON 和 CSV。整个流程仅限于公开商品列表数据,文末的合法性部分不是样板文字,在实际大量抓取前请务必阅读。

你将构建的内容

一个 Node.js 脚本,接受公开的 Walmart 畅销榜类别 URL,通过 Crawling API 获取渲染后的 HTML,并为列表中每件商品提取一条结构化记录。示例使用电子产品畅销榜页面,并为每件商品提取以下字段:

  • 排名:在畅销榜中的位置,从 1 开始。
  • 标题:商品名称,例如"Apple AirPods with Charging Case (2nd Generation)"。
  • 价格:卡片上显示的价格,如"$69.00"。
  • 评分:星级评分文本,例如"4.6 out of 5 Stars"。
  • 评论数:有评论时的数字评论数量。
  • 链接:指向具体商品页面的 URL。

为什么普通请求在 Walmart 上会失败

如果用普通 HTTP 客户端请求 Walmart 畅销榜 URL,你很少能获得商品网格。有两件事对你不利。第一,Walmart 在浏览器中使用 JavaScript 渲染商品卡片,因此初始 HTML 几乎是空外壳,直到页面脚本运行后才会填充。第二,Walmart 对自动化流量的检测非常积极:来自数据中心 IP 以及不像真实浏览器的请求模式,在触及渲染后的商品数据之前就会收到 CAPTCHA 挑战、被限速或被屏蔽。

因此,一个能正常工作的 Walmart 爬虫需要在一次请求中同时满足两点:真正渲染页面的浏览器,以及平台认为是真实访客的 IP。你可以自己搭建一套带有无头浏览器和轮换住宅代理池的方案,但将它们整合并保持健康运行才是工作量的主体。Crawling API 将两者融合为一次调用:你发送 URL,它在受信任 IP 后渲染页面,并返回可用 cheerio 解析的完整 HTML。

两种解析方式

Crawling API 可以返回原始 HTML 供你用 cheerio 解析,也可以传入 autoparse: 'true' 直接获取结构化 JSON。本指南手动编写 cheerio 解析器以便完全控制每个字段和选择器,但当你希望 Crawlbase 为你完成提取时,autoparse 选项始终可用。

前提条件

在编写代码之前,你需要准备好以下几项。每项配置都不需要太长时间。

JavaScript 和 Node.js 基础。你应该能够编写并运行 Node 脚本,并使用 npm 安装包。如果你是 Node 新手,官方文档和任何入门课程都能让你达到本教程所假设的水平。

Node.js 16 或更高版本。使用 node --version 确认版本。如果没有安装,请从 Node.js 官网安装,或通过 nvm 等版本管理器安装。

Crawlbase 账户和 token。注册后,打开控制台,从账户文档页面复制你的 token。免费版提供 1,000 次无需信用卡的请求。请像对待密码一样保管 token:它用于验证你的请求,不要放入版本控制。

配置项目

创建项目文件夹,初始化,并安装爬虫所需的两个库。

bash
node --version

mkdir walmart-best-sellers && cd walmart-best-sellers
npm init -y

npm install crawlbase cheerio

两个依赖库各司其职:crawlbase 是 Crawling API 的官方 Node 客户端,cheerio 以 jQuery 风格的 API 解析返回的 HTML,让你可以通过 CSS 选择器提取各字段。在此文件夹中创建名为 walmart-scraper.js 的文件,并添加以下步骤中的代码。

第一步:获取渲染后的畅销榜页面

首先获取完整页面。导入 CrawlingAPI 类,用你的 token 初始化,并请求畅销榜 URL。在解析之前检查状态码,可以让失败情况更加明显而非悄然发生。

javascript
const { CrawlingAPI } = require('crawlbase');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_TOKEN' });

const walmartPageURL =
  'https://www.walmart.com/shop/best-sellers/electronics';

api
  .get(walmartPageURL)
  .then((response) => {
    if (response.statusCode === 200) {
      console.log(response.body.slice(0, 500));
    }
  })
  .catch((error) => console.error('API request error:', error));

node walmart-scraper.js 运行脚本,你应该在 body 顶部看到真实的 Walmart 商品标记,而非精简的外壳。这确认了渲染工作正常,之后再编写选择器。如果想直接获取解析后的 JSON 而非 HTML,请传入 autoparse 选项,这是不需要自定义选择器时最快的途径。

javascript
// Ask the API to parse the page and return JSON
const options = { autoparse: 'true' };

api
  .get(walmartPageURL, options)
  .then((response) => {
    if (response.statusCode === 200) {
      console.log(JSON.parse(response.body));
    }
  })
  .catch((error) => console.error('API request error:', error));
Crawlbase Walmart Scraper

刚才那次请求在你这边没有任何无头浏览器或代理的情况下,返回了完整渲染的 Walmart 页面。Crawling API 在真实浏览器中运行页面,在服务端轮换住宅 IP,处理 Walmart 向爬虫抛出的 CAPTCHA,为你提供完整的 HTML(或自动解析的 JSON)。先在免费版中测试电子产品畅销榜页面。

第二步:用 cheerio 解析每件商品

拿到渲染后的 HTML,将其加载到 cheerio 中并遍历商品卡片。Walmart 将每件畅销商品布局在一个重复的容器中,因此你只需选取所有卡片,然后从中读取标题、价格、评分、评论数和链接。对每个字段进行防御性读取,可避免单个缺失值导致运行崩溃,而循环索引则提供排名。

javascript
const cheerio = require('cheerio');

function parseBestSellers(html) {
  const $ = cheerio.load(html);
  const products = [];

  const containers = $(
    '.sans-serif.mid-gray.relative.flex.flex-column.w-100.hide-child-opacity'
  );

  containers.each((index, element) => {
    const card = $(element);
    const product = { rank: index + 1 };

    // Title
    product.title = card
      .find('[data-automation-id="product-title"]')
      .text()
      .trim();

    // Price: split the currency symbol from the number
    const priceString = card
      .find('[data-automation-id="product-price"] .w_iUH7')
      .text()
      .trim();
    const priceMatch = priceString.match(/([^\d]+)([\d,\.]+)/);
    product.price = priceMatch
      ? `${priceMatch[1].trim()}${priceMatch[2]}`
      : '';

    // Rating and review count share one block
    const ratingText = card
      .find('.flex.items-center.mt2 .w_iUH7')
      .text()
      .trim();
    const rating = ratingText.replace(/\d+\s*reviews/i, '').trim();
    product.rating = rating !== '' ? rating : 'Rating not available';

    const reviewsMatch = ratingText.match(/(\d+)\s*reviews/i);
    product.reviews = reviewsMatch ? parseInt(reviewsMatch[1], 10) : 0;

    // Link to the product page
    const href = card.find('a[link-identifier]').attr('href');
    product.link = href
      ? new URL(href, 'https://www.walmart.com').href
      : '';

    if (product.title) products.push(product);
  });

  return products;
}

几个细节使代码忠实于页面。商品标题来自 data-automation-id="product-title" 属性,价格在 product-price 块中以"current price $69.00"这样的单一字符串存在,因此用正则表达式将货币符号与数字部分分离。评分块在一段文本中同时包含星级评分和评论数,因此一个正则表达式去掉"N reviews"尾部以保留评分,另一个将评论数提取为数字。链接从卡片锚点的 href 中读取,并解析为绝对 URL,以便在页面外部也能使用。

选择器会发生变化

Walmart 的类名(w_iUH7、长串的 flex flex-column 容器类等)是生成的,会在没有通知的情况下更改。请将上述选择器视为起始模板而非固定合约。当某个字段返回空值时,在浏览器开发者工具中重新检查实时页面并更新选择器。定期维护选择器对任何生产级爬虫来说都是正常的,不是哪里出了问题的迹象。

第三步:组装完整脚本并导出 JSON 和 CSV

现在将获取和解析串联成一个可运行的脚本,然后将记录写入磁盘,分别保存为 JSON 和 CSV。关闭 autoparse 获取原始 HTML,正是 cheerio 解析器所期望的输入。

javascript
const fs = require('fs');
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 toCsv(rows) {
  const headers = ['rank', 'title', 'price', 'rating', 'reviews', 'link'];
  const escape = (value) =>
    `"${String(value).replace(/"/g, '""')}"`;
  const lines = [headers.join(',')];
  for (const row of rows) {
    lines.push(headers.map((h) => escape(row[h])).join(','));
  }
  return lines.join('\n');
}

async function main() {
  const url = 'https://www.walmart.com/shop/best-sellers/electronics';
  const html = await crawl(url);
  if (!html) return;

  const products = parseBestSellers(html);
  fs.writeFileSync('best-sellers.json', JSON.stringify(products, null, 2));
  fs.writeFileSync('best-sellers.csv', toCsv(products));
  console.log(`Saved ${products.length} products to JSON and CSV`);
}

main();

将第二步中的 parseBestSellers 函数粘贴到同一文件中,以便 main 可以调用它。用 node walmart-scraper.js 运行,你将得到两个文件:best-sellers.json 包含完整结构化记录,best-sellers.csv 可直接在电子表格中打开。toCsv 辅助函数对每个字段进行引号处理并将嵌入的引号加倍,这在此处很重要,因为商品标题较长且经常包含逗号。

输出结果是什么样的

JSON 文件按畅销榜顺序存放每件商品的对象,包含排名、标题、价格、评分、评论数和链接。

json
[
  {
    "rank": 1,
    "title": "Apple AirPods with Charging Case (2nd Generation)",
    "price": "$69.00",
    "rating": "4.6 out of 5 Stars.",
    "reviews": 23387,
    "link": "https://www.walmart.com/ip/Apple-AirPods-with-Charging-Case-2nd-Generation/604342441"
  },
  {
    "rank": 2,
    "title": "SGIN 15.6inch Laptop 4GB DDR4 128GB SSD Windows 11",
    "price": "$259.99",
    "rating": "4.5 out of 5 Stars.",
    "reviews": 2697,
    "link": "https://www.walmart.com/ip/SGIN-15-6inch-Laptop/1044996074"
  }
]

CSV 以相同的行加上表头行呈现,可直接放入 Excel、Google Sheets 或任何读取分隔文件的数据管道。

csv
rank,title,price,rating,reviews,link
"1","Apple AirPods with Charging Case (2nd Generation)","$69.00","4.6 out of 5 Stars.","23387","https://www.walmart.com/ip/Apple-AirPods-with-Charging-Case-2nd-Generation/604342441"
"2","SGIN 15.6inch Laptop 4GB DDR4 128GB SSD Windows 11","$259.99","4.5 out of 5 Stars.","2697","https://www.walmart.com/ip/SGIN-15-6inch-Laptop/1044996074"

跨类别扩展

一个类别只是演示;实际工作需要遍历多个畅销榜部门。Walmart 在 /shop/best-sellers/ 下暴露每个部门,因此你可以建立一个类别 slug 列表,通过 Crawling API 获取每个,用相同函数解析,并在导出之前为每行打上类别标签。由于每个畅销榜页面共享相同的卡片结构,你已经编写好的解析器无需修改即可适用于所有类别。

javascript
async function scrapeCategories(categories) {
  const all = [];
  for (const category of categories) {
    const url = `https://www.walmart.com/shop/best-sellers/${category}`;
    const html = await crawl(url);
    if (!html) continue;
    const rows = parseBestSellers(html).map((p) => ({ category, ...p }));
    all.push(...rows);
  }
  return all;
}

scrapeCategories(['electronics', 'toys', 'home']).then((rows) => {
  console.log(`Collected ${rows.length} products across categories`);
});

这个模式可以直接应用于商品研究和价格比较工作。关于将排名列表转化为决策的更深入探讨,请参阅如何自动化电商商品研究;如果你想用另一种语言实现同样的方法,用 Python 抓取 Walmart 搜索的指南涵盖了目录的搜索结果部分。

保持不被屏蔽

即使渲染问题已解决,Walmart 仍会监测爬虫流量。一些好习惯能让运行保持健康,这些习惯适用于任何有挑战性的商业目标。

  • 控制请求节奏。在类别获取之间引入延迟,而不是在紧循环中频繁请求页面。将请求分散开来是保持在 Walmart 限速之内的最关键因素。
  • 依赖轮换机制。住宅 IP 池将请求分散到众多真实用户地址,使任何单一地址都不会触发限速或 CAPTCHA。Crawling API 为你处理这一切;如果你自己搭建方案,这是最重要的部分。
  • 读取状态码。开始返回挑战或非 200 响应的运行在告诉你当前速率或 IP 级别已不够。将其视为退让的信号,而非可忽略的噪声。

关于更广泛的策略,请参阅如何在不被屏蔽的情况下抓取网站。如果你想同时获取另一个市场平台的畅销榜,同样的获取加解析模式适用于 Amazon,相关指南介绍了如何抓取 Amazon 畅销榜

抓取 Walmart 是否合法?

抓取 Walmart 是否被允许,取决于 Walmart 的服务条款、你所在的司法管辖区以及你对数据的使用方式。Walmart 的条款限制了自动访问,因此无论你的工具多么谨慎,抓取行为都可能违反这些条款。本文中的任何代码都不会改变这一点;它只是让技术部分得以实现。请阅读 Walmart 的使用条款及其 robots.txt,并将两者视为采集边界。

有几条值得坚守的原则。只采集公开商品数据:任何人在畅销榜页面上无需账户即可看到的排名、标题、价格、评分、评论数和商品链接。遵守 Walmart 声明的速率预期,保持足够低的请求量,不要给其服务器造成压力。避免采集个人数据,包括任何与可识别评论者相关的信息(超出页面上公开显示的评论文本和星级数量)。不要将 Walmart 的受版权保护的媒体(如商品摄影)重新发布为你自己的内容。如果你计划将数据用于商业目的,请获得许可或官方协议,而不是假设沉默即为同意。

对于大量或商业用途,Walmart 运营着 Walmart 开发者门户Walmart 附属计划,以明确的使用条款提供经授权的商品和目录数据。当你需要大量数据、有保障的结构或商业权利时,这些才是正确的工具。本指南特意限制在公开畅销榜和类别列表范围内,因为这是使工作具有可辩护性的边界。它不涵盖登录墙后的任何内容、客户或卖家个人数据、订单历史,或任何绕过你无权通过的身份验证或 CAPTCHA 的尝试。如果你的项目需要的不只是公开商品列表,正确的途径是 Walmart 的官方 API 或数据协议。

回顾

核心要点

  • Walmart 在客户端渲染商品列表且防护严密。普通请求返回空外壳或 CAPTCHA,因此必须在受信任 IP 后渲染页面才能解析。
  • Crawling API 通过一次调用完成两件事。它渲染页面、轮换住宅 IP 并处理 CAPTCHA;传入 autoparse: 'true' 获取 JSON,或获取原始 HTML 自行解析。
  • cheerio 提取各字段。选取每个商品容器,然后读取标题、价格、评分、评论数和链接,从循环索引推导排名,并预期生成的类名会发生变化。
  • 导出为 JSON 和 CSV。将结构化记录写入两种格式,对 CSV 字段加引号以保持包含逗号的长商品标题完整。
  • 坚守公开数据。遵守 Walmart 的 ToS 和 robots.txt,控制请求节奏,对于大量或商业用途优先使用 Walmart 开发者门户或附属计划。

常见问题

什么是 Walmart 畅销榜?

Walmart 畅销榜是 Walmart 网上商店某个特定部门中销售最快的商品,以排名网格的形式呈现。每个类别(如电子产品、玩具或家居用品)都有自己的畅销榜页面,展示评分最高、最受欢迎的商品。关注这些页面是快速了解当下趋势和购物者正在购买什么的便捷方式。

为什么普通请求从 Walmart 获得的数据不完整?

因为 Walmart 使用 JavaScript 在客户端渲染商品网格,并用 CAPTCHA 挑战自动化流量。来自数据中心 IP 的原始 HTTP 请求通常返回空外壳或拦截页面,而非商品卡片。要获得完整页面,必须在受信任 IP 后渲染它,这正是 Crawling API 为你处理的事。

应该使用 autoparse 还是自己编写 cheerio 解析器?

当你想快速获取结构化 JSON 且默认字段满足需求时,使用 autoparse;传入 autoparse: 'true',API 就会返回解析后的数据。当你需要完全控制提取哪些字段和选择器时,如本指南所做的那样,自己编写 cheerio 解析器,以便精确按你想要的方式塑造记录并添加排名等字段。

我的选择器返回空值。发生了什么变化?

几乎可以肯定是 Walmart 的标记发生了变化。其容器类和生成的类名(如 w_iUH7)会在没有通知的情况下更改,因此上个月还有效的选择器可能已失效。在浏览器开发者工具中重新检查实时页面并更新选择器。定期维护选择器对任何生产级爬虫来说都是正常的。

我可以从 Walmart 抓取客户个人数据吗?

不可以,本指南也不涵盖这方面内容。客户账户详情、订单历史以及登录墙后的任何内容都不是公开数据。抓取登录受限内容、评论者的个人数据(超出公开评论文本),或绕过身份验证,超出了本指南的范围,且违反 Walmart 的条款。对于经授权的访问,正确的途径是 Walmart 开发者门户或数据协议。

如何在抓取 Walmart 时避免被屏蔽?

保持较低的每 IP 请求速率,在类别获取之间添加延迟,并通过轮换住宅 IP 路由,使任何单一地址都不会触发限速或 CAPTCHA。Crawling API 为你管理轮换、受信任的 IP 池和 CAPTCHA 处理;如果你自己搭建方案,这是需要投入的部分。观察状态码,当开始出现挑战时适当退让。

开始构建

大规模爬取任何站点,无需与基础设施对抗。

Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

自助开通 · 无需销售通话 · 提供企业级爬取量