入口页能不能被稳定抓到,除了 URL 本身和响应速度,还有一层经常被忽略的东西:HTTP 缓存头。很多人把它当成纯前端性能优化,实际上在蜘蛛池场景里,缓存配置会直接影响蜘蛛每次到访看到的是 200 还是 304,以及这一次抓取有没有产生新的内容信号。
蜘蛛大体上怎么对待缓存
搜索引擎爬虫不是浏览器,它通常不会像用户那样长期复用本地缓存,也不带 Cookie 和会话状态。但部分爬虫在重复访问同一个 URL 时,会带上条件请求头,例如 If-Modified-Since 或 If-None-Match。这时候服务端的回答就分两种:内容变了返回 200 加新内容,内容没变返回 304。
304 并不等于抓取失败。它只是告诉对方「你手上那份还是最新的」。但对于蜘蛛池入口页来说,入口页的价值就在内容变化上,如果长期只有 304,抓取动作发生了,新内容信号却没有产生。到底你的入口页被问了几次条件请求、返回了多少 304,最靠谱的办法是翻访问日志里的状态码分布,而不是凭感觉。
几个缓存头各自在做什么
- Cache-Control:控制谁来缓存、缓存多久。no-store、no-cache、private、max-age 的含义差别很大,不要混用。max-age 设得过长,中间层可能一直吐旧内容给爬虫。
- ETag:内容的指纹,配合 If-None-Match 使用。多台后端如果各自生成,同一个 URL 可能每次指纹都不同。
- Last-Modified:内容最后修改时间,配合 If-Modified-Since 使用。它应该是真实的内容更新时间,而不是响应生成时间。
- Expires:老式写法,优先级低于 Cache-Control,新旧混用时容易互相打架。
- Vary:告诉缓存哪些请求头会改变响应。写错容易导致缓存命中混乱,出现同一个 URL 两种内容。
常见的几个坑
- 把 no-store 当成「防缓存能提高抓取」的手段。对爬虫来说这通常帮助不大,反而让每次请求都回源,白白增加服务器压力。
- 多节点部署时用默认 ETag 算法(通常基于文件属性和修改时间),同一份内容在不同机器上指纹不同,爬虫每次都被判为「变了」,于是反复拿到 200,消耗掉本可以省下的抓取次数。
- Last-Modified 用当前时间动态生成。结果是每次请求都是「刚更新」,条件请求永远命中不了 304,爬虫看到的更新时间也全是假的。
- CDN 缓存了旧版本入口页,回源策略没配好,爬虫长期抓到的是历史内容,而你本地看到的是新版本,排查时容易误判。
- 反向误区:为了「显得内容常新」而故意频繁改动时间戳。这种信号一旦和实际内容不符,长期看没有正面收益。
缓存头不会让蜘蛛多给你一次抓取,它只决定这一次抓取是否带来新的内容信号。省下来的预算,应该花在真正值得被抓的入口页上。
比较稳的配置思路
- 静态入口页:给一个较短的 max-age(例如几分钟到一小时),同时保留 ETag 和 Last-Modified,让条件请求有正确的判断依据。
- 动态入口页:ETag 用内容哈希生成,保证多节点一致;Last-Modified 取自内容更新时间。
- 内容确实变了:URL 不变就更新 Last-Modified,或者干脆换新 URL 重新进入抓取队列,两种做法各有适用场景。
- 用 CDN 时,确认缓存键是否包含了会改变内容的请求头,并定期抽查回源响应头,别只看边缘节点。
- 入口页的分组、站点之间尽量统一缓存策略,避免同一批资源里有的 200 有的 304,日志分析时会很乱。
一份随手可做的自查
- 用 curl 连续请求同一个入口页两次,看第二次是否返回 304,以及 ETag 是否一致。
- 在多台后端上分别请求同一个 URL,对比 ETag 和 Last-Modified 是否相同。
- 翻日志,统计入口页的状态码分布,看 200、304、404、5xx 各占多少。
- 检查 CDN 回源响应头,确认边缘节点和源站的内容版本一致。
- 改动缓存策略后,隔几天再看一次日志,观察抓取行为有没有变化。
小结
缓存策略本质上是回答一个问题:当蜘蛛再一次来到这个入口页时,你想让它看到什么。想清楚这一点,Cache-Control、ETag、Last-Modified 该怎么配,基本就有答案了。它不解决收录,也不保证排名,但能让有限的抓取动作落在更有意义的地方。