搜索抓取

响应耗时与页面体积:决定蜘蛛单位时间能抓多少的两个变量

抓取能力不只是条数问题,还受响应时间与传输字节数影响。本文拆解 TTFB、响应体大小、重定向与连接开销如何拖慢同域抓取节奏,并给出服务器侧与日志侧的排查顺序,帮你把抓取效率的提升落在消除异常上,而不是盲目压缩页面。

搜索抓取

响应耗时与页面体积:决定蜘蛛单位时间能抓多少的两个变量

聊抓取时,大家习惯数条数:今天抓了多少,还剩多少没抓。但同一台服务器、同样的抓取频次,一个页面用 80 毫秒返回 20KB 的 HTML,另一个用 3 秒返回 900KB,蜘蛛在这两个页面上花掉的时间完全不是一个量级。抓取能力本质上由时间和带宽决定,页面越重、响应越慢,单位时间内能走到的 URL 就越少。

先分清三个变量

影响单次抓取开销的,主要不是页面看起来多复杂,而是下面三件事:

  • 首字节时间(TTFB):服务器把响应开头吐出来的耗时。它决定了蜘蛛的等待时间,等待越长,单位时间能处理的请求越少。
  • 响应体大小:HTML 源码本身的字节数。图片和视频不算在内,但内联的样式、脚本、base64 图片都算。
  • 连接建立与跳转:每条 URL 都要重新建连接、完成 TLS 握手、跟随跳转,这些环节不产出内容,却实实在在占用时间。

慢页面为什么会牵连同域其他 URL

蜘蛛对同一个站点通常维持有限的并发连接数。当若干条请求卡在慢响应上,这些连接就被占着,后面的 URL 只能排队等着。表现出来就是日志里某些页面的抓取间隔被悄悄拉长,而它们自身其实没有任何改动。

需要说明的是,这种影响是相对而非绝对的。短期波动很常见,判断之前最好看一周以上的趋势,而不是盯住某一天的日志下结论。

页面体积里最容易膨胀的部分

  • 把首屏之外的大量内容一次性渲染进 HTML,长列表页尤其常见。
  • 服务端渲染时把整个状态对象塞进 script 标签,内联 JSON 动辄几百 KB。
  • 用 base64 内嵌小图标或字体文件。
  • 导航、页脚、推荐位在每页重复输出,且结构冗长。

这些内容对用户未必没有意义,但对抓取来说属于额外传输量。要处理的是重复和冗余,而不是把有用内容直接删掉。

服务器侧可以做的几件事

  1. 开启 gzip 或 brotli 压缩,HTML 的压缩比通常很高,收益最直接。
  2. 检查数据库慢查询,列表页的响应时间往往随数据量增长而持续恶化。
  3. 让静态资源走缓存或 CDN,减少源站同时处理的请求数。
  4. 减少不必要的重定向,一条 302 就多一个来回,链式跳转更明显。
  5. 对分页、筛选这类高基数页面,确认它们不会拖垮整站的整体响应。

用日志量化一下

多数访问日志会记录响应时间和响应体大小。把一段时间内蜘蛛访问的这两列拉出来,分别算中位数和 P95,比看平均值更有意义——少数几百毫秒的慢请求很容易把平均值带偏。你会看到一些规律:响应体排在前面的 URL,往往集中在列表页和详情页;响应时间异常的,则常常是同几个接口或同一段模板。

顺着这两组数据往下找,通常比漫无目的地翻代码更快定位问题。

目标是让重要页面的响应时间稳定在一个区间,而不是追求某个漂亮的数字。抓取效率的提升大多来自消除异常,而不是把每个页面都压到极限。

哪些页面值得优先减重

不是所有页面都值得投入优化。优先处理的应该是:内链指向多、承载大量 URL 发现的列表页和分类页;被频繁重访的首页与频道页;以及本身就要输出大量结构化数据的页面。这些页面的响应时间改善,会顺着抓取路径放大到整个站点的抓取节奏上。

不要为了抓取牺牲页面本身

把 HTML 做小是好事,但如果代价是首屏内容缺失、必须靠 JavaScript 补齐,渲染环节反而要多花一笔时间,得不偿失。比较合理的顺序是:先修慢查询和多余跳转,再压缩响应体,最后才考虑结构调整。抓取效率只是一个侧面,页面本身的可用性不能因此打折。