抓取几百个页面很容易。抓取几百万个页面则是另一回事,因为在这种规模下,横亘在您和数据之间的不再是解析问题,而是如何保持不被封锁。那些乐于为普通用户服务的网站,对一个在同一地址以固定模式每小时请求数千个页面的客户端,会实施限速、挑战或封禁。数据往往是公开的,但访问模式才是让您被标记的原因。
本指南解释了大规模抓取为何会被封禁,以及真正能让抓取持续运行的方法:轮换 IP 地址、控制请求速率、发送真实的请求头、渲染需要浏览器的页面、只重试失败的请求,以及只为成功的响应付费。文末还介绍了托管抓取 API 如何将所有这些整合为一次请求,并简要说明负责任地采集数据的注意事项。
网站为何封锁大规模抓取
对一个网站而言,一个真人访客就是单个客户端:一个 IP 地址,以人类的速度浏览,点击少数几个页面,带着正常浏览器的指纹。一个未经配置的爬虫看起来完全不同。它从同一个 IP 以远超任何人阅读速度的频率、在可预测的循环中轰炸同一个端点,往往还带着宣告自己是脚本的默认 user agent。这些信号每一个都很容易检测,放在一起则根本无从掩盖。
网站还会通过 robots.txt 文件公布其偏好,列明自动客户端应当和不应当访问的内容以及允许的频率。除此之外,它们还部署了主动防御:按地址的限速、CAPTCHA 挑战、登录墙、浏览器指纹识别,以及对人眼不可见但在 HTML 中可见的蜜罐链接,任何跟随这类链接的客户端都会自我暴露为机器人。这些防御都不是针对人类的,而是专门针对未经配置的爬虫所产生的行为。因此,避免封禁的关键在于不表现得像那些系统所设计来捕获的对象。以下各节将逐一介绍实现这一目标的技术手段。
轮换 IP 地址
您发出的最响亮的信号是来自单一地址的大流量。每分钟从单个 IP 发出一百个请求是最容易被限速的情形,一旦该地址被标记,无论其他设置多么谨慎,来自它的所有请求都会失败。解决方案是将请求分散到多个地址,使任何单一地址都不承载可疑的负载。
这正是代理的用途。代理是位于您的爬虫和目标网站之间的网关,使网站看到的是代理的地址而不是您的地址。轮换代理更进一步,在每次请求时更换该地址,使一个发出一百万次请求的任务分散在大型 IP 池中,而不是集中在单个身份上。代理还有对封锁很重要的类型之分:数据中心地址速度快、成本低,但更容易被识别为非住宅来源;而住宅和移动地址来自真实的消费者网络连接,在防御严格的网站上更容易混入正常流量。关于轮换策略的更深入介绍,请参阅我们的如何使用轮换代理指南。
控制请求速率并遵守限速
即使跨越多个 IP,速度本身也会暴露您的身份。没有人能每秒加载三十个页面,因此做到这一点的爬虫与真实流量的区别一目了然。控制请求速率、添加刻意的延迟,并将请求间隔随机化,会让流量看起来像自然产生的而非机械规律的。
目标是目标网站能够承受而不感到压力的请求速率。这既是礼貌之举,也是有效之策:有节制的爬取远比全速冲刺更不容易触发限速或导致地址被封。许多网站还会通过响应头和状态码直接传达其限制,行为良好的爬虫会读取这些信号并在被要求时退让。将限速视为需要绕过的约束而非障碍,大多数限速问题就会消失。
发送真实的请求头
每个浏览器在每次请求中都会发送一组 HTTP 请求头:标识浏览器和操作系统的 user agent、接受的语言、编码等。默认的爬虫库发送的是稀疏的、明显自动化的请求头集合,有时 user agent 甚至直接写明了 HTTP 客户端的名称。网站会读取这些请求头,不像来自真实浏览器的请求很容易被标记。
将请求头匹配到真实浏览器发送的内容,并在真实 user agent 池中轮换而不是每次请求都重复使用同一个字符串,可以让每次请求都融入正常流量。请求头还需要内部一致:Accept-Language 和 user agent 之间相互矛盾本身就是一个泄露信号。目标是让每次请求与普通人的浏览器发出的请求没有区别,使其在请求本身的层面上没有任何可被识别的特征。
渲染需要 JavaScript 的页面
越来越多的网页不在初始 HTML 中包含内容。单页应用和动态网站加载一个骨架,然后在浏览器中通过 JavaScript 获取并渲染真实数据。向这类页面发出普通 HTTP 请求几乎不会返回任何有用的内容,因为您所需要的内容从未出现在原始响应中。
抓取这类网站意味着需要运行真实的浏览器引擎,让它执行页面的 JavaScript 并等待内容出现后再提取。无头浏览器能处理这一任务,代价是比简单请求更重、更慢,当您运行数百万次这类操作时,这一点很重要。了解哪些页面真正需要渲染,哪些在第一次响应中就返回了所有内容,是让大型任务保持高效而不浪费浏览器时间的关键。我们关于爬取 JavaScript 网站的演示介绍了何时渲染值得付出额外开销。
只重试失败的请求
在大规模运行中,总有一部分请求会失败:暂时性超时、临时封锁、上游响应缓慢。错误的应对是重启整个任务,这会浪费所有已成功的结果,并向目标网站施加双倍的负载。正确的应对是跟踪每次请求的结果,只重试失败的请求,最好带有短暂的退避以让压力较大的端点有时间恢复。
这使大规模抓取既高效又温和。成功的页面已存档且不再重新获取,失败的被单独隔离并自行重试,向网站发送的总流量接近任务实际所需的最低量。以这种方式构建的任务在部分失败时能优雅降级而不是反复挣扎,这正是当运行横跨数小时和数百万 URL 时您所期望的。
在大型任务中手动组合轮换、限速、请求头管理、渲染和重试是许多需要维护的活动部件。Crawlbase Crawling API 将它们整合到一次请求中:它从大型住宅和数据中心池轮换 IP,处理 CAPTCHA 和封锁,在页面需要时渲染 JavaScript,并返回整洁的 HTML。您最多有 20,000 次免费请求供起步使用,且只为成功的请求付费。
只为成功的请求付费
大规模网络抓取有一个经济层面,在账单到来之前很容易被忽视。如果您自建代理群和浏览器农场,您需要为每次发送的请求付费,包括被封锁、超时或返回空内容的请求。在一个故障率不低的百万请求任务中,这些浪费是真实的金钱损失,因为您支付了从未收到的数据的费用。
只对成功响应收费的定价模型改变了这种激励结构。失败请求的成本由提供商承担,这使其利益与您的利益一致:他们有动力保持您的成功率,因为这正是他们计费的基础。这也使大型任务更容易预算,因为您支付的是结果而非尝试。在大规模比较抓取方案时,按请求付费与按成功付费之间的这种区别是较大的成本项之一。
托管抓取 API 如何处理这一切
上述每种技术单独来看都很直接。难点在于将它们全部可靠地组合运行,横跨数百万次请求,并在目标网站更改防御时保持有效。这正是托管抓取 API 所填补的空缺。您无需自行组装和维护代理池、请求头轮换层、无头浏览器农场、重试队列和 CAPTCHA 解决器,只需将 URL 发送到单个端点,就能获得整洁的数据。
在底层,API 在大型 IP 池中轮换地址,将请求的速率和形式调整得像人类一样,发送真实的请求头,在需要时用真实的浏览器引擎渲染 JavaScript 密集型页面,解决或绕过 CAPTCHA,并在返回响应之前重试暂时性失败,所有这些都在返回响应之前完成。对于规模太大而无法同步运行的任务,异步模式让您可以批量提交 URL 并通过回调接收完成的结果,不需要保持数百万个连接打开。结果是反封禁工作成为别人的问题,您将时间花在数据上而不是管道上。关于在这种规模运行任务的更广泛视角,请参阅我们的大规模网络抓取指南和扩展抓取项目的最佳实践。
负责任地抓取
避免封禁是一个技术问题,但它存在于一个伦理问题之中。只抓取公开数据,在开始大型任务之前检查网站的服务条款及其 robots.txt。将您的请求速率保持在合理水平,不要降低服务对其真正目标用户的可用性,因为一个重到能让网站承压的爬取既不礼貌也会适得其反。当您采集的数据包含任何个人信息时,将 GDPR 和 CCPA 等法规视为硬性要求而非事后考虑:只采集您所需要的,尽量聚合,不要建立个人档案。负责任的抓取和不被封锁的抓取方向一致,因为让您保持合规的行为通常也是让您看起来不像滥用机器人的行为。
核心要点
- 被封禁的是访问模式而非数据本身。网站封锁的是在单一地址以固定模式请求过多、过快的客户端,即使数据本身是公开的。
- 轮换和限速完成大部分工作。将请求分散到多个 IP(尤其是住宅 IP),并添加随机化延迟,使流量看起来像人类而非机械。
- 表现得像真实浏览器。发送真实的、多样化的请求头,在页面需要时渲染 JavaScript,使每次请求都与真实流量无从区分。
- 只重试失败的请求并按成功付费。存档成功的页面,隔离并带退避地重试其余部分,优先选择对结果收费而非每次尝试的定价模型。
- 托管 API 整合了这些技术。单个端点将轮换、请求头、渲染、CAPTCHA 处理和重试整合到一次请求中,并为超大型任务提供异步模式。
常见问题
为什么网站封锁爬虫,即使数据是公开的?
封锁很少是针对数据本身的,几乎总是针对访问模式。一个从单一 IP 地址以机器速度在可预测循环中每小时请求数千个页面的爬虫,与人类访客的样子完全不同,而这种行为正是反爬虫系统所设计来捕获的。以类似人类的速率从多样化地址查看的公开数据,远比从单一身份以工业规模抓取的相同数据受到的关注少。
避免被封锁最重要的单一技术是什么?
轮换 IP 地址,因为来自单一地址的大流量是爬虫发出的最响亮、最容易检测的信号。将请求分散到大型 IP 池中(在防御严格的网站上尤其要用住宅或移动地址),可以防止任何单一身份承载可疑负载。话虽如此,轮换与限速和真实请求头结合才能发挥最佳效果,因为即使跨越多个 IP,速度和明显的自动化指纹仍会导致您被标记。
我可以多快抓取而不被封禁?
没有通用数字,因为每个网站设定自己的限制,但原则是保持目标可以轻松承受的速率,并将请求间隔随机化使流量看起来自然。许多网站通过响应头和状态码传达其限制,因此请读取这些信号并在被要求时退让。遵守限速的有节制爬取远比全速冲刺更不容易被限速。
大规模抓取是否总需要无头浏览器?
不需要,能不用就尽量不用,因为渲染比普通请求更重、更慢,当跨越数百万个页面时这一点很重要。只有在网站通过 JavaScript 在初始 HTML 到达后加载内容时,您才需要浏览器引擎。对于在第一次响应中返回所有内容的页面,可以用简单请求抓取,因此高效的方法是只对真正需要的页面进行渲染。
"只为成功的请求付费"是什么意思?
这是一种定价模型,您只为实际返回所需数据的响应付费,而不是为被封锁、超时或返回空内容的请求付费。在故障率不低的大型任务中,这种差异很显著,因为您不需要为从未收到的数据付费。这也使提供商的激励与您的激励一致,因为他们只在您的请求成功时才有收入。
与自建爬虫相比,抓取 API 有何优势?
托管 API 在单个端点后面运行轮换、限速、请求头管理、JavaScript 渲染、CAPTCHA 处理和重试,因此您发送 URL 就能获得整洁的数据,而不需要自行构建和维护这些层次。它还能随着目标网站改变防御而自适应,这在自建方案上是持续的工作量。对于超大型任务,异步模式让您可以批量提交 URL 并通过回调收集结果,而不需要保持数百万个连接打开。
大规模爬取任何站点,无需与基础设施对抗。
Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。