为什么回访比首次抓取更值得关注
新页面发布后,大家关心的通常是“蜘蛛来没来”。但一个页面在生命周期里,被抓取的次数大部分来自回访。蜘蛛判断要不要重新处理一个 URL,核心问题是:内容变了没有。如果服务端能明确告诉它“没变”,它可以省下一次完整下载和解析;如果每次都只能说“变了”,它就只能把整页内容再拉一遍。
条件请求是怎么运作的
蜘蛛回访时,会把上次抓取记录下的信息带回来:
- If-Modified-Since:基于上次响应中的 Last-Modified 时间。
- If-None-Match:基于上次响应中的 ETag 值。
服务端把这两个值和当前内容比对:一致就返回 304,不返回正文;不一致就返回 200 和完整内容。这里有个容易被忽略的点:304 减少的是传输量,不是请求次数。蜘蛛仍然发起了一次抓取,只是拿到的正文更少,它不会因为 304 就给你更多抓取机会。
三种常见的配置问题
Last-Modified 每次都不一样
有些站点的 Last-Modified 取的是页面生成时间、模板渲染时间,或者 CDN 回源时间。结果是同一篇没改过的文章,每次请求返回的时间戳都在变,条件请求永远不命中,蜘蛛每次都得下载全文。
ETag 在多台机器上不一致
部分服务器默认用文件 inode、磁盘路径甚至进程信息生成 ETag。多机、多容器部署时,同一个 URL 在不同节点算出的值不同,蜘蛛带着上次的值回来命中不了,同样只能走 200。
内容没变却上报“变了”
首页和列表页最容易出现这种情况:推荐位、访问计数、时间格式化每次都在变。如果这些变动被算进 Last-Modified 或 ETag,蜘蛛每次都会判断页面已更新,然后反复抓取一份实质上相同的内容。长期下来,既浪费了抓取量,也会让它对站点的更新节奏形成错误印象。
可以怎么改
- Last-Modified 用内容的真实更新时间(例如数据库里的 updated_at),不要用请求时间或渲染时间。
- ETag 用正文内容算哈希,保证同一份内容在不同节点得到相同结果。
- 只有内容确实变化时才更新这两个值,格式调整、计数变化不算内容变化。
- 列表页与首页的变化可以接受,但要控制变动频率和幅度,别让每次访问都像新页面。
- HTML 页面和静态资源分开处理,静态资源的长缓存策略不要直接照搬到动态页面上。
怎么验证配置是否生效
最简单的办法是手动模拟一次条件请求:先记下响应头里的 Last-Modified 或 ETag,再次请求时把它带上,看服务端是否返回 304。也可以回到日志里看同一个 URL 的状态码分布——如果大量 200 响应的字节数几乎一样,往往说明条件请求没有起作用。
别把 304 当成优化目标
304 的价值是减少重复下载和解析,让服务器和蜘蛛都省一点力气,但它不会带来更多抓取。真正决定抓取表现的是站点整体质量、内容更新节奏、服务器响应稳定性这些基础项。
条件请求是给回访“减负”的手段,不是给抓取“加量”的手段。它解决的是重复传输,不解决内容是否值得抓。
和其他抓取因素的配合
304 要和服务器响应速度一起看:一个耗时两秒才返回的 304,比一个快速返回的 200 更拖累抓取。它也不影响 URL 发现——内链和 Sitemap 该暴露的路径还是要暴露。把这几件事分开处理,抓取路径才不会被一个细节卡住。