很多人排查抓取问题时会直接翻源站日志。但如果站点挂了 CDN,蜘蛛的请求很可能压根没到源站——它在边缘节点就被应答了。这时候你看到的「抓取正常」,和蜘蛛实际拿到的内容,可能不是同一份。
蜘蛛拿到的往往是边缘节点的那一份
CDN 的默认逻辑是:命中缓存就直接返回,未命中才回源。蜘蛛的请求通常比真实用户更集中,如果缓存 TTL 较短,或者缓存键里带了 UA、Cookie 之类的变量,蜘蛛很容易每次都触发回源,也可能每次都落到不同节点上的不同副本。
判断方法很直接:用与蜘蛛一致的 UA 发一次请求,看响应头里的缓存标识字段——x-cache、age、cf-cache-status 这类,不同服务商命名不一样。命中与未命中,返回的 HTML 可能差很多。
三类常见的内容不一致
- 版本滞后:源站已经更新,边缘节点还留着旧副本,蜘蛛抓到的是过期页面,页面上指向新栏目的链接自然也不存在。
- 节点差异:不同机房回源时间不同、预热程度不同,蜘蛛从不同出口访问,可能落到新旧两套模板上。
- 降级响应:回源超时或负载过高时,部分配置会返回简化页、验证页甚至 5xx,蜘蛛拿到的就是一份没有出链的空壳。
缓存键里那些容易被忽略的变量
缓存键决定了「哪些请求算同一份」。常见的坑有两个:一是 Vary 头里带了 User-Agent,导致蜘蛛 UA 和普通浏览器 UA 各存一份,缓存命中率被拉低;二是 URL 上带追踪参数,同一篇文章被拆成几十个缓存条目,每个都要回源一次。
这两个问题叠加起来,结果通常是:缓存命中率不高,回源量被放大,源站响应变慢,蜘蛛的抓取节奏随之收紧,覆盖增长也就停了。
排查时可以按这个顺序走
- 拿蜘蛛 UA 请求几个代表性 URL,记录响应头里的缓存状态和 age 值。
- 同一 URL 从不同地区、不同出口多请求几次,对比返回内容是否一致。
- 绕过 CDN 直连源站,对比同一 URL 的 HTML 差异。
- 查 CDN 日志中的回源率、5xx 比例,以及回源超时的阈值设置。
- 核对缓存键配置,确认 UA、Cookie、查询参数是否被无意纳入。
几条可以落地的调整
- 让爬虫 UA 走一条独立的缓存策略,或统一使用浏览器缓存副本,减少同一 URL 的多份存储。
- 页面更新后主动刷新对应 URL 的缓存,而不是等 TTL 自然过期。
- 为回源超时设置合理的兜底:宁可返回上一次的完整副本,也不要返回断链的空页。
- 把分页、筛选参数在 CDN 层做规范化,避免同一内容产生大量缓存条目。
蜘蛛看到的不是你的源站,而是它那一次请求实际命中的那一层。排查抓取问题时,先把这一层对齐,再谈后续的路径和覆盖。