站点运营

站点运营:条件请求与缓存验证自查,别让蜘蛛每次抓取都全量回源

蜘蛛抓取时,条件请求能让内容未变的页面返回 304,减少重复传输。本文说明 Last-Modified、ETag 的常见失效原因,并给出 curl 自查、多节点一致性检查与调整建议,帮助站点运营者把缓存验证配置得更稳定。

站点运营

站点运营:条件请求与缓存验证自查,别让蜘蛛每次抓取都全量回源

蜘蛛抓取页面时,服务器并不需要每次都把完整 HTML 重新发一遍。如果请求里带了验证信息,而内容没有变化,返回一个 304 状态码就能结束这次抓取。这样既省服务器带宽,也减少蜘蛛等待时间。但很多站点在缓存验证头上配置得比较随意,导致条件请求形同虚设,每次抓取都变成全量回源。

条件请求在做什么

浏览器和蜘蛛在第一次拿到页面时,服务器通常会在响应头里给出两个验证器:Last-ModifiedETag。下次再请求同一个地址时,客户端会把这两个值分别放进 If-Modified-SinceIf-None-Match。服务器比较后如果内容没变,就返回 304 Not Modified,不携带正文。

对蜘蛛来说,304 意味着“这个地址我看过了,内容还是老样子”,它可以很快转向下一个地址。如果服务器总是返回 200 和完整正文,蜘蛛就得重新下载、重新解析,抓取效率会下降。

容易被忽略的几种失效情况

验证器每次都在变

有些动态程序会把 Last-Modified 设成当前时间,或者用进程 ID、内存地址生成 ETag。这样每次请求得到的验证器都不一样,条件请求永远对不上,304 自然不会出现。

多节点或多层代理不一致

站点有多台源站或经过反向代理、压缩层时,不同节点给出的 ETag 可能不同。蜘蛛这次请求落到 A 节点,下次落到 B 节点,验证失败,又会拿到 200 响应。

压缩层改写了 ETag

开启 gzip 或 Brotli 后,响应体的字节变了,但 ETag 如果还是按原始内容计算,就可能出现验证不匹配。部分服务器会改用弱 ETag(W/ 前缀),这本身没问题,但要确认整个链路行为一致。

Cache-Control 与验证头冲突

Cache-Control 里写了 no-store 或极短的 max-age,同时又依赖 ETag 做验证,会让中间缓存直接放弃存储,条件请求也失去意义。

304 响应里带了正文

按规范,304 不应包含消息体。如果程序在 304 后面仍然输出页面内容,客户端可能解析异常,浪费一次请求。

自查步骤

  1. curl -I 连续请求同一个 URL 两次,第一次记下 Last-Modified 和 ETag。
  2. 第二次请求时手动带上 If-Modified-Since 或 If-None-Match,观察是否返回 304。
  3. 如果返回 200,对比两次的 ETag 是否变化,以及 Last-Modified 是否等于当前时间。
  4. 在多台源站或多条线路下重复测试,确认验证器一致。
  5. 在访问日志里统计 304 的比例。比例长期接近零,通常说明条件请求没有生效。
  6. 换用蜘蛛 UA 再测一次,排除按 UA 差异化输出导致验证器变化。

调整方向

  • ETag 优先使用内容哈希或稳定的版本号,不要用时间戳、进程号、内存地址。
  • Last-Modified 取自内容最后修改时间,而不是请求发生时间。
  • 源站与代理层统一 ETag 生成规则,压缩层不要随意改写强 ETag。
  • 对长期不变的静态资源,设置较长的 Cache-Control,并保留 ETag 供验证。
  • 对频繁更新的页面,可以缩短 max-age,但不要关闭条件请求。
  • 304 响应只返回头,不输出正文。

和抓取预算的关系

抓取预算有限时,服务器响应速度、状态码、内容是否变化都会影响蜘蛛继续访问的意愿。304 不能直接提升排名,但能减少重复传输,让蜘蛛把时间花在真正变化过的地址上。对内容量大、更新频繁的站点,效果更明显。

抽查时建议固定几个代表性地址:首页、栏目页、详情页、静态资源,分别记录状态码、验证器和响应体积,隔一段时间再对比,看是否有节点漂移。

条件请求属于服务器与协议层面的基础配置,改动不大,但需要定期确认。把它纳入站点巡检清单,和日志、状态码、缓存策略一起看,能避免很多“蜘蛛来了却白跑一趟”的情况。