聊抓取预算时,大多数人只关心一个问题:蜘蛛今天来了几次、抓了多少条。但预算其实是两个维度的乘积——抓取次数和每次抓取的成本。同一个配额下,如果你的页面又慢又重,蜘蛛能走完的 URL 就少,剩下的时间都耗在等待和重试上。
一次抓取要经过哪几段路
从蜘蛛决定抓一个 URL,到它把页面内容读进自己的解析器,中间至少有这么几步:
- 解析域名,拿到 IP;
- 建立 TCP 连接,如果是 HTTPS 还要完成 TLS 握手;
- 发送请求,等待服务器返回第一个字节;
- 接收完整响应体;
- 解析 HTML,提取链接和正文;
- 如果页面依赖 JS 渲染,还要额外下载并执行脚本。
每一段都有耗时,也都可能失败。抓取超时通常不是发生在某一步突然坏掉,而是各段加起来超过了爬虫设定的上限。
首字节时间:服务器端的时间账
TTFB(首字节时间)反映的是服务器从收到请求到吐出第一个字节的耗时。它慢,往往和页面本身没关系,而是后端在等:等数据库慢查询、等缓存未命中后回源、等一个同步调用的第三方接口。
对蜘蛛来说,这段时间它什么都做不了,只能挂着连接。如果站点在抓取高峰时 TTFB 普遍拉长,表现就是蜘蛛抓取变慢、并发上不去,甚至出现大量连接超时。
几个常见的 TTFB 拖累项
- 动态页面每次都实时查询,没有缓存层;
- 页面头部调用了外部接口,接口慢则整页慢;
- 日志、统计类脚本在服务端同步写入;
- 静态资源没有分离,静态请求也走同一套逻辑。
HTML 体积:被忽略的传输成本
很多页面正文只有几 KB,HTML 却有上兆。多出来的部分通常来自:直接内联进页面的 JSON 数据、base64 编码的图片、没有按需加载的组件样式、重复打包的脚本。
体积带来的不只是下载时间。蜘蛛要把这段 HTML 读进内存并解析,页面越大,单次抓取占用的资源越多,同一时间能并行的抓取就越少。
控制体积的几个方向
- 首屏需要的样式和脚本保留,其余延后;
- 数据接口不要整段内联进 HTML,改用异步请求;
- 图片走独立的 URL,不要 base64 塞进正文;
- 开启压缩传输,减少实际字节数。
解析与渲染:JS 重的页面更贵
如果正文和链接是客户端渲染出来的,蜘蛛拿到的初始 HTML 可能几乎是空壳。它需要下载脚本、执行、再取回渲染后的内容,有时还会被排到另一个队列里延后处理。
这不代表必须全站服务端渲染。更实际的做法是分清哪些页面必须能被抓:内容页、分类页、列表页尽量服务端输出,交互密集的页面再交给浏览器执行。
怎么量化一个 URL 的抓取成本
- 在服务器日志里按响应时间和响应字节数分组,看看哪些路径又慢又大;
- 用抓取工具模拟蜘蛛,记录 TTFB、总耗时和 HTML 大小;
- 对比蜘蛛的抓取频次变化,确认优化后是否真的抓得更多;
- 重点关注返回 5xx 或超时的路径,它们最消耗重试额度。
两个常见误区
一是只看首页速度。首页往往有缓存加持,真正拖后腿的是筛选页、搜索页、带参数的分页。这些页面恰恰是蜘蛛容易大量抓到的。
二是把体积问题当成纯粹的用户体验问题。蜘蛛对体积的敏感度和浏览器不完全一样,它更在意能不能在限定时间内拿全内容。用户能忍的加载动画,蜘蛛等不了。
抓取预算不是靠多提交堆出来的,而是靠把每次抓取的成本压下去省出来的。页面轻一点、响应快一点,同样的配额就能覆盖更多 URL。