Scrapy 与 Puppeteer 对比:用于网页抓取

了解两种流行的网页抓取工具——Puppeteer 和 Scrapy。
1 min read
Scrapy与Puppeteer对比用于爬虫

如果没有大量内容供大型语言模型(LLM)进行训练,像 ChatGPT 和 Gemini 这样的 AI 助手就不会问世。其中大量内容是通过网页抓取获取的。

网页抓取不仅对训练 LLM 有用,还可以用于市场分析、价格监控和潜在客户生成。

在本文中,你将比较两种常用的网页抓取工具:ScrapyPuppeteer。Scrapy 是专为网页抓取设计的,而 Puppeteer 是一个无头浏览器模拟框架。值得注意的是,Scrapy 是为 Python 设计的,而 Puppeteer 是为 Node.js 设计的,不过也有一个名为 pyppeteer 的 Puppeteer Python 移植版。

本文将比较每个工具的易用性、抓取速度、功能、社区支持和使用案例。读完本文后,你将对哪个工具适合自己有更好的了解。

Scrapy 与 Puppeteer:易用性对比

Scrapy 是一个完整的框架,需要了解类的使用方法才能开始使用。例如,Scrapy 的核心类是 spider,它定义了应抓取的页面和应解析的元素。还有许多其他类,包括 item、selector 和 ItemLoader。这些类在管道(pipeline)概念中使用效果最好。

尽管文档非常详细,但使用 Scrapy 需要对代码结构有一定的了解。

要安装 Scrapy 并创建项目结构,可以在终端中运行以下命令:

pip install scrapy
scrapy startproject <project_name>

复制

相比之下,Puppeteer 提供了各种用于操作无头浏览器的函数:导航到网站并选择或点击元素。代码结构完全由开发人员自行决定。

开始使用 Puppeteer 只需一个命令,无需创建特定的项目结构:

npm install puppeteer

复制

安装Puppeteer

Scrapy 与 Puppeteer:性能对比

由于采用了不同的方法,Scrapy 和 Puppeteer 在抓取速度方面有很大差异。

Scrapy 向服务器发送 HTTP 请求并处理单个(主要是 HTML)资源的响应。这种方法使 Scrapy 能够异步处理多个页面,遍历 DOM,并选择所需的元素,延迟在亚秒级。

Puppeteer 采用完全不同的方法。作为浏览器模拟软件,它导航到网站,下载所有资源(如图片或外部脚本),并将其加载到浏览器内存中。异步运行多个无头浏览器不建议使用,因为这会对设备性能造成巨大压力,进一步阻碍抓取过程。显然,Puppeteer 在速度方面并不占优势。

Scrapy 与 Puppeteer:功能对比

Scrapy 有三个显著特点:Scrapy shell、中间件和合同:

  • Scrapy shell 运行一个交互式会话,可以用来调试元素选择器。
  • 通过中间件类,Scrapy 支持与其他库集成以应对特定使用场景。例如,Chompjs 可以用来解析 JavaScript 对象,Python 的 Playwright 可以在 spider 中使用以导航动态加载内容的网站。这些功能可以通过使用 Scrapy 中间件类轻松集成到 Scrapy 中。
  • Scrapy spider 可以用合同来约束,合同是一种测试,旨在确定 spider 加载的页面是否符合预期。例如,可以添加一个合同来测试页面加载速度是否足够快或包含所需数量的元素。也可以开发自定义合同。

Scrapy 还拥有丰富的功能来避免被反机器人措施阻止。这包括与代理服务器集成和旋转浏览器指纹(如 User-Agent)。

Puppeteer 也有一些独特的功能,包括截图生成、交互性和时间轴跟踪。由于 Puppeteer 模拟了一个完整的浏览器,它可以完全呈现网页。结果是 Puppeteer 可以将呈现的页面转化为截图甚至 PDF。

Puppeteer 在呈现动态网站方面没有问题,并提供了与之交互所需的工具。通过选择元素、插入文本和点击按钮,Puppeteer 甚至可以用来提交表单。这是选择 Puppeteer 的主要原因之一(稍后会详细介绍)。

Puppeteer 还支持旋转代理,其浏览器指纹可以通过单独调整浏览器参数来操控。如果手动调整这些参数太难,Puppeteer 还有一个名为stealth的插件,使这变得更容易。

Puppeteer 的另一个有趣功能是其生成网页性能审计的能力。这不仅对测试网站有用,还可以用来识别网站服务器是否在限制你的 spider:

Scrapy主页

Scrapy 与 Puppeteer:社区支持

截至 2024 年 2 月 28 日,Scrapy 在 GitHub 上有 1,800 个关注者和 52,000 个星标,各种用户几乎每天都有提交。Scrapy 还有一个 Reddit 社区,每周收到多个问题,大多数问题都有半打以上的答案。如果需要更多支持,Scrapy 还有一个 Discord 社区,并且在 Stack Overflow 上有超过 17,000 个 Scrapy 相关的问题。

相比之下,在 GitHub 上,Puppeteer 的关注者较少(1,200 个),但星标更多(86,000 个),并且每天都有来自不同贡献者的提交。Puppeteer 在 Reddit 或 Discord 上没有官方支持的社区,但在 Stack Overflow 上有超过 8,000 个 Puppeteer 相关的问题。

最后,Puppeteer 和 Scrapy 都有丰富的社区支持的插件或扩展,针对特定使用场景;例如,Scrapy 与无头浏览器集成,以及解析动态网站。

Scrapy 和 Puppeteer 的使用案例

到目前为止,在本文中,你已经简要了解了两个使用案例,以及每个工具在其中一个或另一个中的表现如何:抓取大量静态数据或访问动态加载的数据。

抓取大量静态网页

由于 Scrapy 只加载目标页面的 DOM,因此是用于跨数千个页面的大规模抓取项目的最佳选择。因为它可以异步操作,不下载额外资源,Scrapy 可以同时访问多个网站,轻松抓取几十个网站,延迟在亚秒级。例如,如果你想下载你喜欢的新闻网站上所有文章的评论部分的所有评论,Scrapy 表现出色 。

相比之下,如果你想让 Puppeteer 做同样的事情,它不能只加载单个页面在浏览器中完全呈现。它还会下载额外的图片、脚本和其他嵌入对象,以完全呈现网站,这会产生大量的开销,当列表中包含的页面仅为静态内容时,这通常是不必要的,使用 Scrapy 会比使用 Puppeteer 更快。

抓取动态网页内容

如今,网络不仅专注于在网页上呈现信息,还关注交互性。许多网站已成为图形用户界面(GUI),这意味着以下场景可能会发生:

  • 评论隐藏在阅读评论按钮后,点击该按钮将评论附加到页面上。
  • 内容按标签分组并隐藏在标签后。
  • 文章隐藏在付费墙后,需要登录并提交验证码。
  • 某些网站存在于单个页面上,显示的内容取决于用户的浏览行为。

Scrapy 无法开箱即用地处理这种内容。抓取动态网站需要与中间件集成,例如Splash,或使用浏览器模拟工具,如 Playwright 或 Selenium。

这正是 Puppeteer 真正超越 Scrapy 的地方。其无头浏览器模式使其能够完全加载网页,其 JavaScript 代码提供了网站的交互性。Puppeteer 可以与 Web 应用程序交互,等待 HTML 元素加载(并轮询其存在),选择它们,并在它们可用时下载其内容,而不是尝试访问尚未加载的某些 HTML 元素。

需要注意的是,Scrapy 和 Puppeteer 可以通过使用scrapy-pyppeteer 模块进行集成。如果你对 Scrapy 框架深信不疑,但需要一个无头浏览器来访问动态加载的内容,该模块可能会有所帮助。

结论

Scrapy 和 Puppeteer 是采用完全不同的范式并为不同目标设计的工具。然而,它们都可以用于抓取网页内容。由于这些方法的差异,Scrapy 是用于抓取海量数据的首选解决方案,而 Puppeteer 是导航需要特定用户交互才能呈现某些内容的网站的最佳选择。

然而,这些工具也有共性。它们的社区在某种程度上是可比的,在易用性方面也差不多。它们还有一些共同的功能,如浏览器指纹和代理轮换。

如果你正在寻找一个工具栈来工业化你的抓取工作,请考虑Bright Data,它提供了数百万个代理服务器、抓取 API、专为抓取而设计的浏览器以及现成的数据集。Bright Data 还拥有许多出色的网页抓取文档。例如,你可以了解更多关于Puppeteer 网页抓取的信息,并探索与PuppeteerScrapy的集成。