常见问题

入口页返回 304,搜索蜘蛛还会重新解析页面里新加的链接吗?

入口页日志里出现 304,就以为搜索蜘蛛跳过了页面?其实 304 只是让蜘蛛复用缓存副本,真正的问题往往是缓存内容过期或是空壳。本文拆解蜘蛛处理 304 的顺序,梳理 ETag、Last-Modified、CDN 缓存等常见坑,并给出可执行的自查步骤。

常见问题

入口页返回 304,搜索蜘蛛还会重新解析页面里新加的链接吗?

入口页明明有蜘蛛访问,日志里也记着 304,可页面里新加的目标链接迟迟没有抓取记录。这时很多人会怀疑是 304 让蜘蛛“跳过”了这一页。下面把 304 的实际处理逻辑、容易踩坑的几种情况以及自查方法说清楚。

304 到底意味着什么

304 Not Modified 是服务器对条件请求的回应。搜索蜘蛛再次访问一个已经抓过的 URL 时,通常会在请求头里带上 If-Modified-Since(配合 Last-Modified)或 If-None-Match(配合 ETag)。服务器判断内容没变,就返回 304,不返回正文。

关键点在于:304 表示“用你上次那份就行”,并不等于这次请求被忽略。蜘蛛仍会把这次访问计入抓取记录,并基于缓存的那份 HTML 做链接提取。

蜘蛛遇到 304 之后的处理顺序

  1. 发起条件请求,带上缓存校验信息。
  2. 收到 304,不下载正文,直接取本地缓存的 HTML。
  3. 用缓存 HTML 解析链接,得到目标 URL 列表。
  4. 把发现但未抓取的 URL 放进待抓队列,按调度安排抓取。

所以在正常情况下,304 不会导致链接解析失败。真正让新链接“消失”的,是缓存里那份 HTML 本身就是旧的。

几种容易漏掉新链接的情况

1. 缓存校验条件没跟着内容变

如果 ETag 是按文件大小或某个固定字符串生成的,Last-Modified 又被写死成一个很早的时间,那么入口页即使加了新链接,服务器依然会返回 304。蜘蛛拿到的还是旧 HTML,新链接自然发现不了。

2. CDN 或反向代理缓存了旧页面

源站已经更新,但 CDN 边缘节点还在按 TTL 提供旧内容并返回 304。蜘蛛请求打到边缘节点,结果和上面一样。可以先看响应头里的 Age、X-Cache 之类字段,判断请求命中了哪一层缓存。

3. 页面靠 JS 渲染,缓存的是空壳

如果入口页的链接由前端脚本插入,而缓存下来的是首次渲染前的 HTML,304 之后蜘蛛拿到的仍是空壳。这类页面更依赖服务端直出或预渲染。

304 本身不拦截抓取,它只是让蜘蛛复用已有副本;副本过期或者副本本身就是空壳,才会让新链接一直发现不了。

自查:确认 304 是不是问题源头

  • 用 curl -I 查看正常请求返回的 Last-Modified 和 ETag 取值。
  • 再带 If-Modified-Since 请求一次,看是否返回 304,同时对比本地缓存版本的 HTML 里有没有新链接。
  • 刷新缓存后重新请求,确认返回 200 且正文包含新链接。
  • 对照服务器日志,看蜘蛛拿到的状态码和响应体大小,304 通常没有正文。

降低踩坑概率的做法

  1. 让 Last-Modified 随内容真实变化,不要手工写死。
  2. ETag 使用与内容相关的方式生成,内容变了 ETag 就要变。
  3. 入口页这类需要被频繁重新解析的页面,缓存 TTL 不要设得太长。
  4. 链接尽量写在服务端输出的 HTML 里,减少对脚本渲染的依赖。
  5. 更新入口页后主动做一次缓存刷新,并继续观察后续抓取日志。

总结一下:304 不会阻止搜索蜘蛛解析入口页里的链接,它只是让蜘蛛复用缓存副本。发现不了新 URL 时,先确认缓存副本是不是旧的、是不是空壳,再去看抓取队列和 robots 规则。把缓存校验和缓存层这几处理顺,大多数“加了链接没被抓”的问题都能定位到具体环节。