搜索抓取

304 与蜘蛛抓取:页面没变时,这次请求算不算白跑

抓取日志里经常出现 304,它并不代表抓取失败,而是蜘蛛在确认页面版本是否变化。本文说明 Last-Modified 和 ETag 的校验方式、304 对抓取节奏的影响,以及怎么从日志判断校验是否正常、服务器配置容易踩哪些坑。

搜索抓取

304 与蜘蛛抓取:页面没变时,这次请求算不算白跑

翻抓取日志时,除了 200、3xx 和 5xx,304 出现的频率也不低。它通常不代表抓取失败,而是蜘蛛在问服务器:“这个页面我上次拿到的版本还在吗?”这一问一答,牵涉到站点如何给页面打版本标记,也影响蜘蛛把时间花在哪里。

304 是怎么产生的

蜘蛛第一次抓到一个 URL,服务器返回 200 和页面内容,同时可能在响应头里带上两个字段之一:Last-ModifiedETag。前者是页面最后修改的时间,后者是服务器为这个版本计算出的一个标识。下次蜘蛛再来,会在请求头里带上对应的值,一般叫 If-Modified-Since 或 If-None-Match。

服务器收到后做比对:如果内容没有变,就回一个 304 Not Modified,正文不返回;如果变了,就回 200 并附上新内容。所以 304 的前提是站点支持条件请求,而且版本标记本身是可靠的。

两种校验方式的差别

  • Last-Modified:实现简单,精确到秒。如果页面在几秒内多次修改,或者由程序动态生成时间,容易判断不准。
  • ETag:基于内容或版本计算,粒度更细。但不同服务器生成规则不一样,有时集群里各台机器算出的 ETag 不一致,反倒让蜘蛛每次都拿到 200。

304 对抓取节奏意味着什么

很多人以为 304 是白跑一趟,其实它对双方都有意义。对站点来说,304 省掉了正文传输,带宽和响应时间都更小;对蜘蛛来说,它用一次轻量请求确认页面没变,可以更快把抓取额度挪去别的 URL。日志里看到大量 304,通常说明站点的缓存校验工作正常。

不过,如果整站几乎全是 304,而新页面迟迟没有动静,就要反过来看:是不是新 URL 没有被发现,蜘蛛只能反复确认老页面。这时问题不在 304,而在入口。

从日志里看 304 是不是正常

抓取日志一般有状态码、字节数、User-Agent、请求时间。可以按下面几步看:

  1. 筛出蜘蛛 UA 的请求,按状态码分组,确认 304 的占比。
  2. 把返回 304 的 URL 和返回 200 的 URL 放在一起看,是否覆盖了主要栏目。
  3. 如果某类页面长期返回 200,而内容明明没变,检查响应头里有没有 Last-Modified 或 ETag。
  4. 如果同一 URL 在短时间内被重复请求多次,看是不是分页、筛选参数或内链把同一个地址拆成了多个入口。

服务器配置上容易踩的几个点

一是动态页面没有输出校验头,蜘蛛每次都要重新下载全文。二是 ETag 规则不一致,负载均衡后面多台机器各算各的,蜘蛛拿到的标记对不上,只能一直收到 200。三是中间有缓存层或 CDN,缓存的响应头被改写,校验值到源站对不上。四是页面模板里带了会变化的时间戳,Last-Modified 每次都更新,但正文其实没动。

304 不是异常,也不是省事的开关。它更像一次确认:版本没变,就少传一次内容;版本变了,就该老老实实回 200。

怎么配合蜘蛛的校验

对大多数内容站来说,让页面正确输出 Last-Modified 或稳定的 ETag 就够了。文章类页面用发布时间作为 Last-Modified 比较稳妥;列表页、首页这类聚合页面更新时间较频繁,可以按实际最后一次变动来标。重要的是不要让校验值抖动:内容没动,标记就保持不变。

如果站点已经在用 Sitemap 或提交接口给蜘蛛提供新地址,那校验机制管的是已知 URL 是否更新,和新 URL 发现是两条线,不要指望 304 去解决抓取入口的问题。

最后,观察 304 的变化趋势比盯单次请求更有用。改版、迁移或模板调整之后,304 比例突然掉得很低,往往说明响应头配置被改动了,值得回查一次。