网络爬取是搜索引擎、价格监控系统以及几乎所有大型网络数据集背后的引擎,但这个词掩盖了大量的工程细节。爬虫不仅仅是一个循环下载页面的程序,它是一个系统,需要决定跟进哪些链接、以何种顺序、以何种速度,以及如何在合理的时间内完成任务的同时避免重复下载同一页面。把这些决策做对,爬取就能干净地扩展到数百万个 URL;做错了,它就会停滞、陷入循环,或者在前一千次请求时就被封锁 IP。

本指南将梳理区分健壮爬虫和初级爬虫的核心网络爬取技术,然后概览团队在不想从头构建这些机制时所会选择的框架。读完之后,你将理解爬取如何实际遍历网络、每种技术背后的权衡,以及哪种工具适合你手头的任务。

什么是网络爬取?

网络爬虫,也称为蜘蛛或网络机器人,通过跟进链接自动发现和下载页面。它从一组种子 URL 开始,抓取每个页面,提取其中的链接,并将新发现的链接添加到待访问的 URL 队列中。如此循环,爬虫就向外遍历一个网站乃至更广泛的网络,构建一份所发现内容的记录。搜索引擎是最初的应用场景:其爬虫对页面内容进行索引,使其能够出现在搜索结果中。

在此过程中,爬虫收集的不只是原始 HTML。它记录每个页面的 URL、标题和元信息、正文内容,以及出站链接及其指向的位置。它会记录已下载的 URL,以避免重复抓取同一页面,并能标记失效链接,或随时间对比同一页面的不同版本。相同的机制还驱动着各种实际应用,如网站存档、构建产品目录、监控竞争对手价格,以及追踪新闻和社交来源中的提及。

爬取与抓取相关但有所区别。爬取是发现和遍历步骤,即找到并获取页面;抓取是提取步骤,即在已获取页面的基础上从标记语言中提取特定字段。大多数实际项目两者兼用,但以下技术关注的是爬取:如何高效、礼貌地遍历网络,且不陷入僵局。

核心网络爬取技术

本节涵盖的技术是每个认真对待爬取的系统都必须做出的决策,无论你是自行编写还是继承自某个框架。它们涵盖页面的访问顺序、工作队列的管理方式、爬虫如何成为其所访问网站的良好公民,以及如何处理通过 JavaScript 动态构建内容的现代页面。

广度优先与深度优先遍历

网络是一个图结构,遍历顺序决定了你首先收集到什么。广度优先爬取先访问所有与种子页面相距一跳的页面,再访问相距两跳的所有页面,如此扩散推进。这是通用爬取的常见默认选择,因为它能快速覆盖网站的广泛浅层样本,并倾向于优先找到高价值页面(这些页面通常被大量其他页面引用)。深度优先爬取则沿一条路径尽可能深入,再回溯,在探索同级页面之前先深入挖掘一个分支。

在实践中,用 FIFO 队列实现的广度优先爬取主导着大型爬取任务,因为它覆盖均匀且易于限定范围。由堆栈支撑的深度优先适用于你希望在转入下一部分之前彻底穷举某一区域的场景,例如爬取单个深层嵌套的商品目录。许多爬虫采用混合策略,通过评分(链接流行度、页面深度、新鲜度)对队列进行优先级排序,而非严格的广度或深度优先,使最有价值的页面优先被抓取。

URL 边界与去重

等待爬取的 URL 队列称为边界(frontier),对其进行良好管理是爬虫实现规模化的关键所在。边界决定下一个 URL 是哪个,执行排序和优先级,并向抓取器提供数据。在任何实际规模下,它都必须存储在内存之外(在数据库或分布式队列中),因为已发现的 URL 列表增长速度远快于已访问的 URL 列表。

与之相伴的问题是去重。同一页面可以通过许多 URL、追踪参数和重定向链到达,因此,若没有去重步骤,爬虫会反复下载相同的内容并可能陷入无限循环。标准的解决方案是对每个 URL 进行规范化处理(主机名转小写、去除默认端口、丢弃片段和已知追踪参数),然后与已见过的 URL 集合进行比对。对于非常大的爬取任务,该集合通常是一种内存高效的数据结构,如布隆过滤器,它只需完整列表所需内存的一小部分,就能回答"我是否见过这个 URL?"这个问题。

礼貌性与速率限制

一个尽可能快地发出请求的爬虫会使小型服务器过载,并导致自身被限速或封禁。礼貌性是指对请求节奏进行控制,以避免爬取对所访问的网站造成伤害。核心规则是每主机延迟:限制每秒向任何单一域名发送的请求数量,并在对同一主机的请求之间添加短暂等待,即使同时在并发爬取许多其他主机。

良好的礼貌性结合了几个习惯。按域名而非全局限制并发数,以免单个网站遭受请求洪泛。遵守网站所公告的任何 Crawl-delay,并在遇到错误或响应缓慢时降低请求频率,因为一台正在挣扎的服务器应该受到更少的访问,而不是更多。除了礼貌之外,这也具有实用价值:温和的、经过识别的流量远比激进的爬取更难触发速率限制,因此礼貌性和可靠性指向同一个方向。

遵守 robots.txt

大多数网站在其根目录发布一个 robots.txt 文件,说明爬虫可以和不可以访问哪些路径,以及规则适用于哪些用户代理。一个行为良好的爬虫在爬取某个主机之前,会先获取并解析该文件,然后跳过所有被禁止的路径。该文件还可以公告 Crawl-delay 并指向网站的 sitemap,而 sitemap 是网站希望被爬取的 URL 的现成列表。

遵守 robots.txt 是对自动化流量的基本期望,也是一个负责任爬虫最清晰的标志。按主机缓存已解析的规则,以免频繁重新抓取该文件,并定期刷新,因为规则会发生变化。Sitemap 值得直接使用:它们通常会呈现仅靠跟进链接会错过的页面,并提示每个 URL 的新鲜程度,这有助于上述的优先级决策。

处理 JavaScript 渲染

越来越多的网站在浏览器中构建其内容。普通 HTTP 请求返回的 HTML 几乎是空的,直到客户端 JavaScript 运行并注入真实内容之后才完整。一个只读取初始响应的爬虫在这些页面上几乎什么都看不到。要爬取它们,你需要像浏览器一样渲染页面,这意味着运行一个无头浏览器(如由 Puppeteer、Playwright 或 Selenium 驱动的浏览器),执行脚本并返回完整构建的 DOM。

渲染功能强大但代价高昂:真实浏览器比 HTTP 请求消耗多得多的 CPU 和内存,因此你不会希望对每个页面都进行渲染。通常的做法是检测哪些目标确实需要渲染,仅对那些进行渲染,对静态页面保持廉价的请求路径。有关这种分流的深入分析,请参阅如何爬取 JavaScript 网站,其中介绍了何时需要渲染,以及如何防止渲染主导你的爬取预算。

分布式爬取

单台机器每秒只能抓取有限数量的页面。超过一定规模后,爬取任务必须分散到多台工作节点上,这就是分布式爬取。边界成为一个共享队列,多个抓取器并行地从中拉取 URL,去重集合也是共享的,以避免两个工作节点爬取同一页面。做得好的话,吞吐量随工作节点数量接近线性扩展。

难点在于协调和礼貌性。工作必须进行分区,使对特定主机的所有请求都通过同一个工作节点或速率预算进行路由,否则十个工作节点各自"礼貌地"访问同一个网站,合在一起就变成了一次不礼貌的洪泛。状态(边界、已见集合、结果)必须在各机器间共享且保持一致。正是这种协调开销,使许多团队宁愿将大型爬取任务交给托管服务,而不是自行运营分布式集群。

Crawlbase Crawling API

分布式爬取、轮换、渲染和重试是爬虫中最难构建、也最难持续维护的部分。Crawlbase Crawling API 接收一个 URL,负责处理 IP 轮换、JavaScript 渲染和封锁后的自动重试,返回干净的 HTML,让你保留自己的遍历和解析逻辑。对于大型任务,异步 Crawler 允许你推送 URL 并通过回调接收结果,从而无需自行管理工作节点集群或代理池,即可大规模爬取。

增量爬取与聚焦爬取

爬取一次很少能完成全部工作。网络在不断变化,因此已对某个网站建立索引的爬虫,需要在不重新下载所有内容的情况下重新访问它。增量爬取追踪变化并有选择地重新抓取,利用页面的最后修改日期、其在 sitemap 中的条目,或其此前的变化频率等信号,使频繁更新的页面得到频繁重访,而静态页面则被忽略。这样可以在不每次都承担完整重新爬取成本的情况下,保持大型索引的新鲜度。

聚焦爬取在另一个维度上进行收窄:与其尝试覆盖所有内容,它只追踪与某个主题或模式相关的页面。爬虫对每个发现的链接进行评分,评估其通向目标内容的可能性,并优先处理有希望的链接,同时剪掉偏离主题的分支。例如,一个垂直的价格监控系统,会跟进产品和分类链接,而忽略其他所有内容。这两种技术的核心都是把有限的爬取预算花在真正值得的地方,而不是无差别地爬取一切。

广度优先与深度优先。同一棵链接树,以两种方式访问:广度优先逐层推进(宽而浅的覆盖),而深度优先则沿一个分支一路向下,再回溯(深入且聚焦的爬取)。数字标注了访问顺序。

网络爬取框架

很少有团队从零开始实现边界、去重、礼貌性和渲染机制。框架将这些技术打包成可复用的工具,让你通过配置来完成一次爬取,而无需搭建底层管道。以下所列举的是成熟且被广泛使用的选项,大致按从轻量脚本端到重型搜索引擎规模的顺序排列,并加入了不希望自行运营爬取基础设施的团队可以选择的托管方式。

Scrapy

Scrapy 是 Python 生态中最流行的爬取框架,也是自定义爬虫的通常起点。它提供了完整的管道:一个可以并发抓取多个页面的异步引擎、一个管理边界的请求调度器、自动的链接跟进、重试机制,以及内置的将结构化数据导出为 JSON、CSV 或 XML 的功能。你编写蜘蛛来定义从哪里开始以及如何解析每个页面,Scrapy 在底层处理并发和队列。它是针对数千到数百万页面的周期性爬取任务的正确选择,要求具备结构性和可控性。原生 Scrapy 不执行 JavaScript,但在目标需要渲染时,它可以与浏览器工具集成。

Apache Nutch

Apache Nutch 是一个成熟的开源爬虫,专为网络规模爬取和与搜索世界的紧密集成而构建。它运行在 Apache Hadoop 之上,因此其爬取任务在设计上就分布于集群之中,并且可以插接 Apache Solr 或 Elasticsearch 等索引后端。Nutch 围绕经典的搜索引擎爬取循环构建(生成抓取列表、抓取、解析、更新爬取数据库),并通过协议、解析器和过滤器的插件系统进行扩展。它比 Scrapy 更重,面向需要爬取网络中大量页面、并需要久经考验的 Hadoop 支撑管道的团队。

Heritrix

Heritrix 是互联网档案馆(Internet Archive)构建的网络爬虫,用于为 Wayback Machine 抓取页面。它专为彻底、存档质量的爬取而设计,以标准 WARC 格式写入输出,该格式保留了完整的请求和响应数据,用于长期存档。Heritrix 在范围规则、礼貌性和抓取内容方面高度可配置,并默认严格遵守 robots.txt。当目标是对页面进行忠实、完整的保存时(如构建网络存档),而不是为了分析而提取少量字段时,应选择 Heritrix。

StormCrawler

StormCrawler 是一套用于在 Apache Storm 上构建低延迟、可扩展网络爬虫的资源集合。由于 Storm 是一个流处理系统,StormCrawler 以持续流式方式而非批次方式进行爬取,这适合需要持续获取新鲜数据的场景,如新闻和监控爬取。它是模块化的、基于 Java 的,允许你从用于抓取、解析和索引的组件中组装一个爬取拓扑。它与 Nutch 处于相似的定位,但相比 Nutch 以批次为导向的模型,它更倾向于持续的实时爬取。

使用 Crawlbase 进行托管爬取

上述框架为你提供了爬取逻辑,但将网络问题留给你自己解决:轮换 IP、渲染 JavaScript、解决或规避 CAPTCHA,以及重试被封锁的请求。托管爬取服务承接了这一层。使用 Crawlbase,你发送一个 URL,就能获得渲染后的 HTML,代理轮换和反封锁处理均在服务端完成,而异步 Crawler 则将大型批次加入队列,并通过回调传递结果。它并不替代你的爬取策略,种子选择、遍历和解析仍由你负责,但它消除了大规模运行时最难维护的基础设施部分。

框架一览

下表将每个框架与其最擅长的场景和适合的项目类型进行映射,以便你根据自身任务进行选择,而不是默认使用上次用过的那个。

框架 最适合 类型
Scrapy 自定义爬取,数千到数百万页面 Python 框架
Apache Nutch 网络规模、Hadoop 支撑的搜索爬取 分布式爬虫
Heritrix 存档、全保真页面抓取 (WARC) 存档爬虫
StormCrawler 持续的、低延迟监控爬取 流式爬虫
Crawlbase 无需反封锁基础设施的托管爬取 Crawling API / 异步 Crawler

没有任何一行能回答所有爬取场景。Scrapy 涵盖大多数自定义工作,Nutch 和 StormCrawler 处理网络规模和持续爬取,Heritrix 专注于存档,而托管 API 则接管了所有开源框架都无法开箱解决的轮换和渲染问题。

负责任地爬取

无论使用哪种技术或框架,都应克制地爬取。尊重每个网站的服务条款及其 robots.txt,专注于公开可获取的数据,而非任何你无权访问的登录内容,并保持合理的请求速率,以免对你所依赖的服务器造成压力。通过用户代理如实标明你的爬虫身份,并提供联系方式。负责任的节奏也符合自身利益:温和、行为良好的流量被封锁的概率远低于激进的爬取,因此良好的规范和可靠的爬取往往指向同一个方向。

回顾

核心要点

  • 遍历顺序至关重要。广度优先提供均匀、可限定的覆盖范围,是通常的默认选择;深度优先深入单个分支;许多爬虫则通过评分对边界进行优先级排序。
  • 边界和去重是核心。良好管理的 URL 队列加上 URL 规范化和已见集合(在规模较大时通常是布隆过滤器),可防止爬取陷入循环或重复下载页面。
  • 礼貌性让你保持畅通。每主机速率限制、限制并发数,以及遵守 robots.txt,既保护了你所爬取的网站,也保障了你自身爬取的可靠性。
  • JavaScript 和规模增加了成本。只对需要浏览器的页面进行渲染,并在将每个主机路由到单一速率预算的前提下分布到多个工作节点,以保持礼貌性。
  • 框架封装了底层机制。Scrapy 适合大多数自定义爬取,Nutch 和 StormCrawler 处理网络规模和持续任务,Heritrix 专注存档,托管 API 则承接轮换和渲染。

常见问题

网络爬取和网络抓取有什么区别?

爬取是发现和遍历步骤:从种子 URL 开始,跟进链接,抓取页面以发现更多页面。抓取是提取步骤:一旦获取到页面,就从标记语言中提取特定字段。大多数项目两者兼用,用爬取到达页面,用抓取从中提取数据,但它们是具有不同关注点的独立阶段。

爬虫应该使用广度优先还是深度优先遍历?

广度优先是通用爬取的常见默认选择,因为它能快速提供宽泛、均匀的覆盖范围,且易于用 FIFO 队列进行限定。深度优先适用于你希望在转入下一部分之前彻底穷举某个深层区域的场景。许多生产爬虫两者都不严格遵循,而是通过链接流行度、深度或新鲜度等评分对边界进行优先级排序,使最有价值的页面优先被抓取。

什么是 URL 边界?

边界是爬虫已发现但尚未访问的 URL 队列。它决定下一个 URL 是哪个,执行排序和优先级,并向抓取器提供数据。在规模较大时,它通常存储在数据库或分布式队列中,而不是内存里,因为已发现的 URL 列表增长很快。与去重相结合,它是保持爬取有序并防止无限循环的关键。

爬虫如何避免重复下载同一页面?

它们对每个 URL 进行规范化处理(主机名转小写、去除默认端口、丢弃片段和追踪参数),并在加入队列之前,与已见过的 URL 集合进行比对。对于非常大的爬取任务,该集合通常是一种内存高效的数据结构,如布隆过滤器,它只需完整列表所需内存的一小部分,就能判断某个 URL 是否曾被见过。

网络爬虫必须遵守 robots.txt 吗?

遵守 robots.txt 是对行为良好的自动化流量的基本期望,也是一个负责任爬虫最清晰的标志。一个好的爬虫在爬取某个主机之前会获取并解析该文件,跳过被禁止的路径,遵守公告的爬取延迟,并使用其所指向的 sitemap。结合合理的速率限制和如实的身份标识,这是负责任爬取的核心。

我应该使用哪个网络爬取框架?

这取决于你的任务。Scrapy 适合数千到数百万页面的大多数自定义爬取。Apache Nutch 和 StormCrawler 面向网络规模和持续爬取。Heritrix 专为存档和全保真抓取而构建。如果难点在于保持畅通而非爬取逻辑本身,托管爬取 API 负责处理轮换、渲染和重试,让你专注于遍历和解析。

开始构建

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

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

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