返回博客

使用 Node.js 实现 Cheerio 数据抓取:2025 年指南

-
Mastering Web Scraping with Cheerio NPM cover
目录
-

核心要点

  • Cheerio 提供类似 jQuery 的高效 HTML 解析方式,使网络数据抓取更简便,并可将结果保存为 JSON 格式。
  • 它适用于静态网页,无需借助重量级浏览器即可快速提取数据。
  • 将 Cheerio 与 Axios 等 HTTP 客户端(以及可靠的代理)配合使用,可实现稳定的数据抓取,并将数据输出为 JSON 格式。
  • 抓取数据时请遵守相关规范:尊重网站规则,并使用速率限制和代理以避免被封锁。

Cheerio 是一个用于解析 HTML 和 XML 的 Node.js 库,本质上相当于服务器端的 jQuery,拥有相似且熟悉的 API,常用于在不借助浏览器的情况下抓取网页。

它不会像浏览器那样渲染页面或加载外部资源,而只是解析 HTML,并以轻量级的 DOM 结构呈现内容。实际上,使用 Cheerio 进行数据抓取,可以借助熟悉的选择器从页面 HTML 中提取数据。

何时使用 Cheerio

如果您需要一种轻量级的抓取工具,从静态网页中获取结构化内容,Cheerio 会是合适的选择。只要所需数据已存在于页面 HTML 中(无需用户交互或复杂脚本),Cheerio 通常都能胜任。

例如,使用 Cheerio 可以快速抓取商品列表或博客文章。当可以直接获取原始 HTML 时,它非常适合用于网页数据提取。

不过,Cheerio 并非浏览器,不会执行任何 JavaScript 代码或页面事件。这意味着,如果某个网站依赖客户端 JavaScript 来显示内容(例如动态加载数据的单页应用),仅靠 Cheerio 可能无法获取所需信息。

在这种情况下,您可能需要借助无头浏览器或其他工具来处理动态内容(后文会进一步说明)。

优缺点

优点:Cheerio 快速高效(无需浏览器开销,仅需解析 HTML),如果您熟悉jQuery,上手会非常容易。您可以快速构建抓取工具解析大量静态页面,并且能轻松与 Node 工具集成(例如将结果保存为 JSON 文件)。

缺点:Cheerio 无法执行脚本或与页面交互。如果网站通过JavaScript加载数据,或需要点击登录,仅靠 Cheerio 无法获取这类内容。由于 Cheerio 依赖特定选择器,一旦网站 HTML 结构发生变化,您的抓取逻辑也可能失效。对于高度动态或需要登录的网站,使用无头浏览器工具或官方 API 可能更合适。

搭建数据抓取环境

在开始数据抓取之前,请确保已安装 Node.js 和 npm。本指南建议使用Node.js 18.x 或更高版本(较新版本的 Cheerio 需要 Node 18 及以上)。

您可以从官方网站下载 Node.js(其中已包含 npm),可以使用适用于您系统的官方安装程序,也可以通过包管理器(例如 Linux 上的 nvm)获取最新的 LTS 版本。安装完成后,在终端中执行 node -v 和 npm -v 进行验证。

安装 Cheerio 和 Axios

接下来,为抓取工具创建一个项目文件夹,并在其中执行 npm init -y 进行初始化,然后安装所需的库:

npm install cheerio axios

这会将 Cheerio(用于解析 HTML)和 Axios(用于发送 HTTP 请求)添加到项目中。Axios 是一个基于 Promise 的 HTTP 客户端,可以在 Node 中轻松获取网页内容。

注意:如果您计划进行大量数据抓取,可能还需要配置代理或使用代理相关的包。接下来我们会介绍代理的使用,包括 MarsProxies 能提供哪些帮助。

创建项目结构

现在为抓取工具创建一个入口文件,例如 index.js,在编辑器中打开它并引入所需模块:

const axios = require('axios');
const cheerio = require('cheerio');
const fs = require('fs');

这里我们引入了 Axios、Cheerio 以及 Node 的文件系统模块(fs),用于将数据保存为 JSON 文件。

2025 年用 Cheerio 抓取网页数据不被封锁

获取住宅代理

使用 Cheerio 进行数据抓取:分步讲解

接下来,我们一步步构建一个简单的数据抓取项目。本示例将使用允许抓取的公开沙盒网站Books to Scrape。

第一步:使用代理

网站通常会通过 IP 地址追踪抓取行为,如果发现大量请求来自同一个 IP,就可能对其进行限速或封锁。使用代理可以帮助将请求分散到不同的 IP 上,让抓取行为更难被检测。如果您需要抓取大量网页,或目标网站有严格的反抓取机制,代理会特别有用。

在 Node.js 中,您可以配置 Axios 使用代理。例如,使用 MarsProxies 时,您会获得代理主机地址、端口和登录凭证,然后可以这样配置:

const proxyConfig = {
  host: 'PROXY_HOST',
  port: 1234,
  auth: { username: 'USER', password: 'PASS' }
};
const response = await axios.get('http://books.toscrape.com', { proxy: proxyConfig });

这会让请求通过代理发送。如果您使用的是轮换住宅代理(例如 MarsProxies 提供的产品),每次请求都可以通过不同的 IP 发出,从而降低被封锁的风险。少量页面的抓取即使不使用代理也能顺利完成,但大规模抓取则离不开代理。如果 Amazon 也是您的抓取目标之一,我们专门的Amazon 数据抓取指南介绍了您需要了解的具体挑战和技巧。

第二步:发送 HTTP 请求

抓取的第一步是获取页面的 HTML,使用 Axios 可以轻松实现:

const url = 'http://books.toscrape.com';
const response = await axios.get(url);
const html = response.data;

这会向目标 URL 发送 GET 请求,并将页面 HTML 存储在 html 变量中(对于返回 JSON 的 API,Axios 会直接给出解析后的数据)。

第三步:将 HTML 加载到 Cheerio

接下来,将 HTML 字符串加载到 Cheerio 中:

const $ = cheerio.load(html);

此时,$ 对象即代表 Cheerio 中页面的 DOM,相当于在服务器端使用 jQuery 操作网页。您可以使用 $ 来选择元素并浏览页面内容。

第四步:选择元素并提取数据

借助 Cheerio 类似 jQuery 的语法,您可以通过 CSS 选择器查找元素并获取文本或属性。例如,如果每本书都列在 <article class="product_pod"> 元素中(标题位于 <h3> 链接内,价格位于 <p class="price_color"> 中),可以这样编写:

const books = [];
$('.product_pod').each((i, element) => {
  const title = $(element).find('h3 a').attr('title');
  const price = $(element).find('.price_color').text();
  books.push({ title, price });
});

这段循环会遍历每一条书籍信息,获取链接的 title 属性和价格文本,并将它们作为包含 title 和 price 字段的 JSON 对象添加到 books 数组中。

提取数据后,您可以保存或使用这些数据。例如,将 books 数组保存为 JSON 格式:

fs.writeFileSync('books.json', JSON.stringify(books, null, 2));

这会将结果以 JSON 格式写入文件。

常见问题与局限性

处理 JavaScript 渲染的内容

Cheerio 只能看到服务器返回的 HTML。如果网站是在页面加载后通过 JavaScript 填充内容,使用 Cheerio 提取数据时就会遗漏这部分内容。

在这种情况下,您可能需要通过 API 获取数据(如果网站提供返回 JSON 数据的 JSON 端点),或者使用无头浏览器(例如 Puppeteer 或Selenium)获取完整渲染后的页面,再将该 HTML 交给 Cheerio 解析。

避免 IP 封锁与速率限制

如果数据抓取过于频繁,网站可能会封锁您的 IP。为避免这种情况:

  • 控制请求频率。在请求之间加入延迟,或限制每秒发送的请求数量,避免对服务器造成过大压力。
  • 使用代理并进行轮换。像 MarsProxies 这样的服务可提供轮换 IP 地址,使网站看到的请求来自不同来源,而非单一来源。
  • 随机化请求模式。变化请求的时间间隔,并使用不同的 User-Agent 字符串,使其更接近正常用户的浏览行为。

应对 HTML 结构变化

网站的页面布局可能随时发生变化,从而导致抓取工具失效。建议使用灵活的选择器,避免依赖过于脆弱的假设。

例如,依赖特定选择器(如某些 nth-child 位置)可能存在风险。如果抓取工具无法再找到数据,请检查更新后的 HTML,并相应调整选择器或逻辑。维护抓取工具往往意味着需要不断适应这类变化。

Cheerio 与其他抓取工具的对比

Cheerio 与 Puppeteer 的对比

Cheerio 和 Puppeteer 适用于不同的需求。Cheerio 是一种快速的 HTML 解析工具,适合处理静态内容;Puppeteer 则控制真实的无头 Chrome 浏览器,可以抓取动态内容。

Cheerio 更快、更轻量(无需运行浏览器),但无法执行 JavaScript 或模拟用户交互。Puppeteer 则可以完成真实浏览器所能做的一切,例如加载动态数据,但速度较慢且消耗更多资源。

在需要速度和简洁性的静态数据抓取任务中使用 Cheerio,而在需要执行脚本或与页面交互时使用 Puppeteer。

Cheerio 与 Selenium 的对比

Selenium 是另一种浏览器自动化工具,功能上与Puppeteer类似(常用于测试 Web 应用)。两者的对比也类似:Cheerio 轻量,而 Selenium 则驱动真实浏览器来处理动态页面。

如果您只需要解析静态 HTML,Cheerio 会简单得多。如果目标内容需要运行真实浏览器(例如登录或执行 JS),Selenium 可以做到,但代价是速度较慢、复杂度更高。Selenium 能完成 Cheerio 无法完成的任务,但开销更大。

何时将 Cheerio 与其他工具结合使用

有时,将两类工具结合使用是更合适的方案。例如,您可以使用 Puppeteer 或 Selenium 登录网站或完整加载页面,然后获取该页面的 HTML 并交给 Cheerio 进行解析和数据提取。

这种混合方式既能处理动态内容,又能享受 Cheerio 在元素选择和解析方面的便利:用浏览器自动化工具处理交互和 JS,再让 Cheerio 快速从生成的 HTML 中筛选出所需数据。

合规数据抓取的最佳实践

速率限制与请求节流

请始终控制抓取的节奏。短时间内发送过多请求会给服务器造成压力,并可能被标记为机器人活动。建议在请求之间加入短暂延迟,或限制每秒发送的请求数量。这样做既能降低被检测的风险,也能减轻目标网站的负担。

避免法律与合规风险

在抓取任何网站之前,请先查看该网站的 robots.txt 文件和服务条款,因为部分网站明确禁止数据抓取;只抓取公开可用的数据,切勿尝试访问未获授权的私密信息或账户。

避免任何可能对网站造成损害的操作(例如用大量请求使其过载),并负责任地使用代理;简单来说,请遵守网站政策、合理获取数据——礼貌地抓取数据能降低被封禁的概率。

Cheerio 和 jQuery 有什么区别?

Cheerio 是一个在服务器端解析 HTML 的库,而 jQuery 运行在浏览器中,用于操作实时的 DOM 元素;Cheerio 模仿 jQuery 的语法,但不处理事件或动态页面更新。

Cheerio 和 Puppeteer 相比,哪个更适合?

对于注重速度和简洁性的静态网页,Cheerio 更合适;而对于动态内容,由于 Puppeteer 运行完整的无头浏览器,因此更合适。

Cheerio 能否抓取动态内容?

不能直接抓取:Cheerio 只能读取静态 HTML,不会执行 JavaScript,因此无法抓取动态加载的内容。

进行数据抓取会被发现吗?

会,尤其是在请求发送过快过多或忽视网站规则的情况下;使用 MarsProxies 等代理并增加请求间隔,有助于降低被检测到的概率。

了解更多
-

相关文章