蜘蛛池知识

蜘蛛池入口页的缓存协商:Last-Modified 与 ETag 该不该给蜘蛛用

蜘蛛回访入口页时不会直接下载整页,而是先做一次缓存协商。本文讲清 Last-Modified、ETag、Cache-Control 各自的作用,304 状态码对蜘蛛池的实际影响,以及时间戳不更新、动态 ETag 这类常见坑,并给出几条可落地的配置建议。

蜘蛛池知识

蜘蛛池入口页的缓存协商:Last-Modified 与 ETag 该不该给蜘蛛用

入口页放上去之后,蜘蛛不会只看一次。第二次、第三次来的时候,它通常并不想重新下载整页 HTML,而是先发一个带条件的请求,问服务器:这个 URL 从我上次拿到的版本到现在,有没有变过。服务器如果回答「没变」,蜘蛛就只拿一个 304 状态码走人。这个过程就是缓存协商,靠的主要是 Last-Modified 和 ETag 两个响应头。

三个头各自管什么

  • Last-Modified:页面最后一次修改的时间。蜘蛛下次请求会带上 If-Modified-Since,服务器比对时间,没变就返回 304。
  • ETag:内容的指纹,常见做法是文件修改时间加大小,或者内容哈希。蜘蛛带 If-None-Match 回来比对。
  • Cache-Control / Expires:管的是浏览器和 CDN 的缓存时长,对蜘蛛本身没有强制约束,但会影响 CDN 是否回源,间接影响蜘蛛看到的内容新旧。

304 对蜘蛛池意味着什么

蜘蛛池的入口页通常数量多、单页内容薄。如果每一页每次被抓都完整回传一遍 HTML,出口带宽和响应时间都会被吃掉。返回 304 的好处很直接:传输量小、响应快,蜘蛛能在同样的时间预算里多走几个 URL。但这不等于「304 越多越好」。

如果入口页的内容确实变了,却因为 Last-Modified 没更新而返回 304,蜘蛛会继续认为这一页还是老样子,新加的内链、新换的标题都不会被重新读取。对做 URL 发现的池子来说,这种情况比多花一点带宽更麻烦。

缓存头的作用是让蜘蛛少做无用功,不是让蜘蛛看不到变化。

几个常见误区

  1. 动态生成 ETag。有些程序用进程 ID 或请求时间戳拼 ETag,同一份内容每次请求指纹都不同,蜘蛛每次都判定为「变了」,协商形同虚设,反而比不做更费资源。
  2. Last-Modified 写成当前时间。为了显得更新频繁,每次请求都返回 now(),结果是每次都全量回传,还把页面真实的修改时间抹掉了。
  3. 只改内容不改时间。用模板批量插入内链或调整版式时,忘了更新文件时间或清缓存,Last-Modified 停在几周前,蜘蛛回来拿到 304,改动等于白做。
  4. 把 Cache-Control 设得很长,又指望蜘蛛快点看到新内容。这两个设置服务的是不同对象,CDN 缓存长不代表蜘蛛会慢,但可能造成回源内容和缓存内容不一致。

配置上的几点建议

  1. 静态 HTML 入口页交给 Web 服务器自动处理 Last-Modified 和 ETag,不要手动覆盖。
  2. 动态生成的入口页,用内容哈希算 ETag,或者干脆只给 Last-Modified,保证同一份内容的指纹稳定。
  3. 内容有实质变化时同步更新时间戳;只改了空白或注释,不必强行刷新。
  4. 用访问日志观察 304 与 200 的比例。全是 200 说明协商没生效;全是 304 而内容明明更新过,说明时间戳维护有问题。
  5. 不要把缓存协商当成提升抓取量的手段。它省的是重复传输,并不改变蜘蛛愿不愿意来。

最后提醒一句:缓存头解决的是「同一份内容别重复传」的问题,它跟内容质量、URL 结构、站内路径设计是几件不同的事。把它做对,只是让蜘蛛在入口页上少浪费一点时间;真正决定蜘蛛愿意走多远的,还是那些页面上有没有值得继续爬的东西。