使用JavaScript和Node.js进行网络爬虫:Cheerio与Puppeteer
Lead Scraping Automation Engineer
关键要点:
- 第一个决定是静态与动态,它决定了整个工具链。 如果数据在初始 HTML 中,使用 Cheerio 进行解析;如果 JavaScript 构建数据,则需要像 Puppeteer 这样的真实浏览器。
- Cheerio 是解析器,而不是浏览器 —— 这正是重点。 它加载 HTML,并以原生速度提供 jQuery 风格的选择器,没有渲染开销,仅适用于内容已在标记中的页面。
- Puppeteer 渲染,因此它查看用户所见。 对于客户端渲染的页面、无限滚动和交互后面的内容,Puppeteer 运行 JavaScript 并交给你完成的 DOM。
- 两者都在同一个 Scrapeless 会话中运行。 通过云浏览器获取 HTML,然后使用 Cheerio 解析或通过 Puppeteer 实时提取——底层具有相同的反检测和住宅出口。
- 并行验证。 以下相同的目录页面通过 Cheerio 产生 20 项,通过 Puppeteer 也产生 20 项——证明当内容存在时,两条路径一致。
- 免费开始。 新的 Scrapeless 账户包括免费的抓取浏览器运行时——在 app.scrapeless.com 注册。
介绍:为页面选择正确的工具
JavaScript 和 Node.js 非常适合网络抓取——这是浏览器运行的相同语言,具有成熟的 HTTP 和 HTML 生态系统。但是“用 Node 抓取”立即分为两种截然不同的工作,选择错误的一个会浪费精力。
如果你想要的数据已经在页面的初始 HTML 中,你根本不需要浏览器——你需要的是一个快速的解析器。这就是 Cheerio:加载标记,运行选择器,完成。如果数据是在加载后由 JavaScript 构建的——一个 React 应用程序、无限滚动的动态信息、仅在点击后出现的内容——那么解析器什么也看不见,因为它解析的 HTML 是一个空壳。这就是 Puppeteer(或 Playwright)发挥作用的地方:它运行页面的 JavaScript 并给你渲染的 DOM。
两个工具下的实际问题是访问:真实网站会进行指纹识别、限速和地域封锁。本指南在 Scrapeless 抓取浏览器上同时运行这两种方法——一种反检测云浏览器——因此获取成功,然后展示何时使用 Cheerio,何时使用 Puppeteer。以下两种路径都在同一页面上实时运行。
静态与动态:如何判断
| 静态(Cheerio) | 动态(Puppeteer) | |
|---|---|---|
| 数据的位置 | 在初始 HTML 中 | 加载后由 JS 构建 |
| 工具 | 解析器 | 真实浏览器 |
| 速度 | 快,开销低 | 较慢,渲染页面 |
| 适用情况 | 服务器渲染的页面、文章、目录 | 单页面应用程序、无限滚动、点击后内容 |
快速测试:查看页面源代码(而不是检查器)。如果数据在原始 HTML 中,Cheerio 就足够了。如果源代码是一个几乎空的壳,内容仅在实时 DOM 中显示,则需要 Puppeteer。
为什么选择 Scrapeless 抓取浏览器
Scrapeless 抓取浏览器是一个可定制的、反检测的云浏览器,专为网络爬虫和 AI 代理设计。对于 Node 抓取,它特别提供:
- 标准的 Puppeteer 连接 ——
Puppeteer.connect()返回一个正常的Browser,因此你的代码没有变化。 - 云端 JS 渲染 —— 动态页面实际上构建它们的内容,因此
page.content()(用于 Cheerio)和实时提取都能正常工作。 - 195多个国家的住宅代理 —— 准确的出口确保获取成功并保持一致。
- 反检测指纹识别 —— 会话呈现为真实浏览器,因此页面渲染,而不是挑战。
- 会话持久性 —— 在多页面运行之间保持 Cookie 有效。
在免费计划上获取你的 API 密钥,访问 app.scrapeless.com。
前提条件
- Node.js 18 或更高版本
- Scrapeless 账户和 API 密钥——在 app.scrapeless.com 注册
- 对 CSS 选择器有基本了解
安装
bash
npm install @scrapeless-ai/sdk puppeteer-core cheerio
bash
export SCRAPELESS_API_KEY="your_api_token_here"
连接
javascript
import { Puppeteer } from '@scrapeless-ai/sdk';
const browser = await Puppeteer.connect({
apiKey: process.env.SCRAPELESS_API_KEY,
sessionName: 'js-node-scraping',
proxyCountry: 'US',
sessionTTL: 300,
});
const page = await browser.newPage();
await page.goto('https://books.toscrape.com/', {
waitUntil: 'domcontentloaded',
timeout: 60000,
});
路径 A — Cheerio(静态解析)
当内容在 HTML 中时,使用 page.content() 获取标记,并使用 Cheerio 解析。选择器 API 采用 jQuery 风格,因此阅读起来很自然:
javascript
import * as cheerio from 'cheerio';
const html = await page.content();
const $ = cheerio.load(html);
const titles = $('.product_pod h3 a')
.map((i, el) => $(el).attr('title'))
.get();
console.log(titles.length, '—', titles[0]);
// 20 — A Light in the Attic
Cheerio 不会渲染任何内容——它只是解析你提供的字符串。这使得它在已经持有 HTML 时快速且理想。你也可以在任何来源的 HTML 上使用它,而不仅仅是浏览器。
在免费计划中获取你的 API 密钥:app.scrapeless.com
路径 B — Puppeteer(动态提取)
当内容由 JavaScript 构建时,从渲染页面的实时 DOM 中提取。相同的选择器,但在页面脚本运行后在浏览器中评估:
javascript
const titles = await page.evaluate(() =>
[...document.querySelectorAll('.product_pod h3 a')].map((a) => a.getAttribute('title')),
);
console.log(titles.length, '—', titles[0]);
// 20 — A Light in the Attic
在同一目录页面,两个路径返回相同的 20 个标题——因为内容在 HTML 中存在,无论哪种方法都有效。区别在于客户端渲染的页面:Cheerio 在原始 HTML 中找不到任何东西,而 Puppeteer 路径仍然返回项目,因为页面首先进行了渲染。
对于在交互时加载的动态内容,在提取之前驱动页面——滚动以获取懒加载内容,点击以显示,然后在结果上 waitForSelector:
javascript
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForSelector('.product_pod', { timeout: 10000 });
// ...然后如上提取
选择它们之间的方式
- 原始 HTML 中有内容吗? 使用 Cheerio——它更快、更简单。
- 内容由 JavaScript 构建、无限滚动或在点击后出现吗? 使用 Puppeteer 进行渲染,然后提取。
- 一个页面上都有内容? 很常见——用 Puppeteer 渲染,然后将
page.content()传递给 Cheerio 如果你更喜欢其选择器在静态部分的易用性。
返回的内容
当数据存在时,任何路径都会生成相同的扁平列表:
json
{
"count": 20,
"first": "A Light in the Attic"
}
// 实际捕获:Cheerio 和 Puppeteer 都从同一页面返回了 20 个标题。
一些诚实的观察:
- 在不必要时不要渲染。 如果 HTML 已经有数据,Cheerio 完全跳过渲染成本。
- 当源是一个外壳时渲染。 一个几乎为空的原始 HTML 与一个填充的实时 DOM 是使用 Puppeteer 的信号。
- 在内容上等待,而不是时钟。 对于动态页面,
waitForSelector优于固定的setTimeout。 - 选择器是共享知识。 相同的 CSS 选择器在 Cheerio 和
querySelectorAll中有效,因此在路径之间移动成本低。
结论:一个决定,两个干净的路径
使用 JavaScript 和 Node.js 进行网页抓取归结为一个早期的调用——数据是在 HTML 中,还是由 JavaScript 构建?Cheerio 执行第一个案例,以解析速度处理;Puppeteer 通过渲染页面处理第二个案例。在 Scrapeless 抓取浏览器上同时运行意味着无论如何抓取都成功,底层有住宅出口和反检测。若要了解更深的反机器人工作流程,请参阅 Scrapling + Scrapeless 指南;抓取浏览器产品页面 和 文档 覆盖了完整的 SDK 表面。首先检查原始 HTML,在可以的情况下选择 Cheerio,在必须时选择 Puppeteer,等待内容而不是时钟。
准备构建你的 AI 驱动的数据管道?
加入我们的社区,申请免费的计划,并与构建 Node 抓取工具的开发者连接:Discord · Telegram。
在 app.scrapeless.com 注册,获取免费的抓取浏览器运行时,并将上述模式应用于你的工作流程所需的静态和动态页面。有关规模的信息,请参见 定价。
常见问题
问:我什么时候应该使用 Cheerio 而不是 Puppeteer?
当数据已存在于页面的初始 HTML 中。Cheerio 只是解析标记,因此它更快且更简单——无渲染。当 JavaScript 构建内容时使用 Puppeteer。
问:我如何知道一个页面是静态的还是动态的?
查看原始页面源(而不是检查器)。如果数据在源中,它就是静态的——Cheerio 有效。如果源是一个几乎空的外壳且内容仅出现在实时 DOM 中,则它是动态的——使用 Puppeteer。
问:我可以在同一页面上使用两者吗?
是的。使用 Puppeteer 渲染,然后将 page.content() 传递给 Cheerio,如果你更喜欢其对于静态部分的选择器操作。
问:Cheerio vs Playwright vs Puppeteer — 选哪个?
Cheerio 用于静态解析。Puppeteer 或 Playwright(都是完整浏览器)用于动态渲染 —— 选择你的技术栈已使用的那个;Scrapeless 会话可以与两者通过 CDP 一起使用。
问:我需要代理吗?
对于公共静态页面,通常不需要 — 但固定 proxyCountry 会提供一个一致的住宅 IP,真实网站将其视为正常访客,这在扩展时更加重要。
问:我可以不使用 AI 代理运行这个吗?
可以。它是 Scrapeless SDK 加上普通的 Puppeteer 和 Cheerio — 不需要代理。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



