很多站长给入口页开了缓存校验(Last-Modified / ETag)之后,发现日志里入口页的状态码变成了 304,于是产生疑问:蜘蛛这次到底有没有读到页面内容?里面的目标链接还会不会被发现?要回答这个问题,先要弄清 304 是怎么来的。
304 是怎么产生的
304 Not Modified 不是服务器主动返回的,而是对条件请求的回应。搜索蜘蛛第二次、第三次访问同一个 URL 时,通常会在请求头里带上 If-Modified-Since 或 If-None-Match,把上次拿到的 Last-Modified 时间或 ETag 值回传。
- 服务器比对后认为文件没变,返回 304,响应体为空(0 字节)。
- 服务器认为变了,返回 200,重新下发完整 HTML。
- 服务器不支持条件请求,忽略请求头,直接返回 200。
所以 304 代表的是“和上次一样”,而不是“这次没抓”。
蜘蛛遇到 304 时通常怎么处理
从抓取调度的角度看,304 是一个正常且成本很低的结果。多数搜索引擎会把这次访问计入抓取统计(日志里确实有一次请求),并沿用上一次缓存下来的页面内容与链接关系。也就是说:
- 页面里的链接大概率不会被重新完整解析一遍,因为内容被认为和上次是同一份。
- 该 URL 的抓取频率可能维持甚至略微下降,服务器说没变化,调度上就少了重抓的理由。
- 如果入口页的链接是按时间轮换、由脚本动态插入的,那么“内容没变”的判定本身就可能出错。
关键差别在于:入口页的作用是持续暴露新的目标 URL,而 304 的前提是“内容没变”。这两者天然有点冲突。所以问题不在于 304 是否被处理,而在于你的入口页到底有没有真的发生变化。
什么样的入口页容易被 304 卡住
页面内容确实长期不变
入口页写好后几个月不动,链接列表固定,这时返回 304 是合理的,链接发现也早已完成,不构成问题。
内容会变,但校验逻辑没有跟着变
常见几种情况:按天生成缓存但文件时间戳忘了更新;ETag 由前端模板 ID 生成,改了链接列表 ETag 却没变;反向代理或 CDN 把旧的校验值原样透传回来。此时爬虫看到的一直是“没变”,新的目标链接就迟迟暴露不出去。
怎么判断入口页有没有被真正重读
- 看服务器日志里 200 与 304 的比例。如果入口页长期几乎全是 304,而你每周都在换链接,那就不正常。
- 看响应体大小。304 的响应体是 0 字节,200 才会带上 HTML 体积,日志里同时记录这两列,问题会一目了然。
- 看 User-Agent 与访问时间分布,确认是搜索蜘蛛而不是自己的缓存探针触发的 304。
- 小范围验证:手动改一条链接再观察,如果依然是 304,说明校验值没有跟着内容更新。
处理建议
- 不要为了“让蜘蛛多来”就强行关掉缓存校验。每次都返回 200 会消耗更多带宽,也可能把抓取预算花在没必要的地方。
- 让校验值跟着内容走。ETag 或 Last-Modified 应基于页面真实内容生成,而不是固定值或模板版本号。
- 入口页更新要改到能被检测到的程度。链接的增删与顺序调整都算变化,只改不可见的注释不算。
- 新的目标 URL 优先单独提交。入口页负责长期暴露,提交负责快速发现,两者是互补关系。
- 适当分散入口页。不要把大量链接挤在一个长期不变的页面上,否则 304 一旦卡住,影响面会很大。
304 本身不是错误,也不会直接导致目标 URL 不被抓取。真正需要关注的是:入口页的内容变化,有没有被服务器的校验逻辑如实反映出来。
最后提醒一句,抓取和收录是两件事。入口页被正常重读、目标 URL 被成功抓取,都不等于一定会收录,最终还是取决于目标页面自身的质量和站点整体表现。