排查抓取问题时,很多人只盯着源站:状态码对不对、HTML 有没有坏、内链通不通。但从蜘蛛发出请求到拿到 HTML,中间还隔着缓存与 CDN。这一层如果配置不一致,蜘蛛看到的页面可能和用户看到的不同,甚至和它上一次抓到的完全一样。
蜘蛛的请求先落在哪一层
常见链路是:蜘蛛 → DNS → CDN 边缘节点 → 源站。如果边缘节点上有可用副本,请求不会再回到源站。这意味着源站日志里根本不会出现这次抓取,而蜘蛛拿到的可能是几小时甚至几天前的版本。只看源站日志做抓取分析,很容易漏掉这一部分访问。
命中与回源的区别
- 命中缓存:响应快,源站没有日志,返回内容取决于副本年龄,响应头里的 Age 可以反映这一点。
- 回源:源站产生日志,返回当前版本,但延迟更高、资源消耗更大。
- 回源失败:可能返回 5xx,也可能被缓存下来,在一段时间内持续影响抓取。
几类容易踩到的不一致
缓存时间设得过长
HTML 文档如果被设置了很长的 s-maxage 或 max-age,内容更新后边缘节点仍返回旧版。蜘蛛再访时看到的内容没变化,自然不会判断为更新过的页面。动态页面通常更适合短缓存加回源校验,长缓存留给长期不变的资源。
缓存键把蜘蛛和用户分开了
有些配置会按 User-Agent、Cookie 或设备类型区分缓存。如果蜘蛛的 UA 命中了另一份副本,你看到的页面和它看到的可能不是同一份。响应里的 Vary 头能反映这类分歧,排查时要留意。缓存键分得越细,副本越多,不一致的概率也越高。
回源错误被当成正常内容缓存
源站短暂 5xx 或超时,如果缓存规则把错误响应也存了下来,蜘蛛接下来一段时间会持续拿到错误结果。表现为源站已经恢复,抓取却仍然失败。这类问题往往要等缓存过期才自行消失。
JS、CSS 被缓存层额外拦截
部分站点在 CDN 上对静态资源和脚本做了额外限制,蜘蛛拿不到完整的渲染资源,看到的页面结构与实际不符。这类情况常常表现为抓取正常,但内容不完整。
用蜘蛛的视角做一次自查
- 用蜘蛛的 User-Agent 请求关键 URL,对比与浏览器请求返回的 HTML 是否一致。
- 查看响应头中的 Age、Cache-Control、X-Cache、CF-Cache-Status 等字段,确认是命中还是回源。
- 把源站日志和 CDN 日志对一遍,找出只有 CDN 有记录、源站没有的抓取请求。
- 对同一 URL 连续请求两次,观察第二次是否返回同一份副本,判断缓存颗粒度。
- 在内容更新后立刻用蜘蛛 UA 请求一次,确认拿到的是新版本而不是旧副本。
缓存层与抓取稳定性的关系
缓存命中率下降时,回源请求会成倍增加,源站压力上升,超时和 5xx 的概率也随之变大。蜘蛛遇到连续的失败响应会放慢节奏,短时间内就不再频繁回访。所以缓存配置不只是性能话题,它间接决定了服务器能不能稳住抓取流量。
内容更新之后可以做的事
- 更新重要页面后,主动刷新对应 URL 的缓存,而不是等 TTL 自然到期。
- 给 HTML 设置较短的缓存时间,把长缓存留给图片、字体这类不常变的资源。
- 缓存键尽量简单,避免按 UA 分叉出多份 HTML 副本。
- 让回源错误不进入缓存,或者把错误响应的缓存时间设得极短。
- 服务器压力大的时候观察回源比例,命中率下降往往先于抓取异常出现。
缓存不是抓取优化的技巧,而是抓取链路上的一环。它决定了蜘蛛实际拿到什么,而不是你希望它拿到什么。
蜘蛛看到的页面是整条链路末端的结果,源站只是其中一段。把 CDN、反向代理和源站三处的返回版本对一遍,很多“抓取正常但内容不对”的问题会变得容易解释,也更容易定位到具体该改哪一层。