蜘蛛池知识

蜘蛛池入口页的响应头:Last-Modified、ETag 与缓存字段怎么设

入口页的正文写得再细,响应头如果是服务器默认值,爬虫对内容类型、更新节奏和缓存版本的判断就只能靠猜。本文梳理 Content-Type、Last-Modified、ETag、Cache-Control、X-Robots-Tag 等字段在蜘蛛池场景下的常见设法和容易踩的坑,并给出一份可以直接照着检查的清单。

蜘蛛池知识

蜘蛛池入口页的响应头:Last-Modified、ETag 与缓存字段怎么设

蜘蛛爬到一个入口页时,最先读到的并不是页面里的文字,而是服务器返回的响应头。状态码决定这一趟值不值得继续,响应头则决定下次还要不要来、以什么方式缓存、把这段字节当成什么来解析。很多入口页在正文上花了不少功夫,响应头却全是服务器默认值,爬虫对这页的更新节奏和内容类型只能靠猜,猜错的代价就是白跑一趟。

响应头是爬虫读取的第二道信息

响应行之后,每一个字段都会被解析器按顺序读走。不同字段的权重不一样,但有一条规律是共通的:字段缺失或前后矛盾时,爬虫倾向于走保守路径——少来、慢来、按旧内容处理。所以响应头不一定要写得多花哨,但至少要自洽。

Content-Type:别把 HTML 发成别的类型

  • 入口页应当返回 text/html 并带上正确的 charset。charset 缺失时,爬虫要靠内容嗅探来猜编码,猜错就是乱码。
  • 如果服务器把页面返成 text/plain 或 application/octet-stream,解析器可能根本不当它是一个网页来处理。
  • 响应头里声明的编码要和页面 meta 里写的一致。两处打架时,不同爬虫的取舍顺序并不统一。

Last-Modified 与 ETag:告诉爬虫内容变了没有

这两个字段的核心用途是让爬虫判断资源有没有变化,从而决定是重新拉取全文,还是只做一次轻量确认。

  • Last-Modified 精度到秒。批量生成的入口页如果所有页面的时间戳完全一致,这个信号基本就废了;反过来,如果每次请求时间都在变但内容没变,爬虫会认为你在制造假更新。
  • ETag 建议基于内容摘要生成,而不是随机数或进程 ID。基于内容生成时,内容不变 ETag 就不变,爬虫的比对才有意义。
  • 两个字段同时存在且不冲突时,效果最好。只剩一个也能用,但不要出现 ETag 变了而内容没变的反复抖动。

Cache-Control 与 Expires:缓存时间不是越长越好

缓存字段在这里会经过两层:一层是爬虫自身的缓存策略,一层是 CDN 或反向代理的中间缓存。

  • 更新频繁的入口页,如果设了很长的 max-age,爬虫和中间层都可能拿到旧版本,你改了正文,外面的视图还是老的。
  • 长期不变的入口页可以设长一些,减少重复传输。
  • 需要每次确认的场景,用 no-cache 比 no-store 更合适——允许缓存,但要求回源校验。no-store 会让任何一层都不留副本,抓取开销反而变大。

X-Robots-Tag 与其他容易被漏掉的字段

  • X-Robots-Tag 的效果和页面里的 meta 指令类似,但它藏在响应头里,改模板时最容易忘记同步。排查入口页为什么没被继续处理时,这个字段要优先看一眼。
  • Content-Length 与实际字节数不一致,会让部分客户端提前截断或等待超时。
  • 3xx 场景下的 Location 应当指向真实可达的地址,避免链条过长。跳转本身怎么做是另一个话题,但响应头里至少要保证目标稳定。
  • Vary 字段如果用得随意,会让缓存命中率忽高忽低,间接影响爬虫拿到的版本。

一份可以照着过的检查清单

  1. 状态码与响应头是否自洽,正文长度和 Content-Length 能不能对上。
  2. Content-Type 是否为 text/html,charset 是否和页面 meta 一致。
  3. Last-Modified 是否反映了真实的最近一次内容修改,而不是部署时间或进程启动时间。
  4. ETag 是否随内容变化,且不会无故抖动。
  5. Cache-Control 是否与这页的更新频率匹配。
  6. X-Robots-Tag 是否和模板里的 meta 指令保持一致,没有互相矛盾。
  7. 批量抽查几台机器、几条线路,确认响应头是同一套,而不是被某层代理改写过。
响应头能让爬虫更准确地理解入口页的类型和变化,但它只解决“看得懂”的问题,不解决“会不会收录”的问题。把响应头理顺是基本功,不是捷径。