蜘蛛来抓入口页,走的是 HTTP,就会遇到缓存。缓存本来是为用户和带宽服务的,但在蜘蛛池里,它会同时影响三件事:蜘蛛每次看到的内容版本、源站要扛多少回源请求,以及你在访问日志里判断是否正常的那套依据。入口页往往改动不多,很多人顺手配一条长缓存,等真要加链接、换指向的时候才发现,蜘蛛看到的还是旧版本。
三层缓存要分开看
把缓存当成一个整体,很容易配错。实际至少有三层:
- 浏览器与客户端缓存:由 Cache-Control、Expires 控制。搜索引擎蜘蛛虽然也是客户端,但通常不会像浏览器那样长期复用本地缓存,这层对蜘蛛影响有限,但对普通访客和部分抓取工具存在影响。
- CDN 或反向代理缓存:这是蜘蛛池里最容易出问题的一层。蜘蛛请求到的是边缘节点,节点命中缓存就直接返回,不回到源站。内容更新了但节点没刷新,蜘蛛拿到的就是旧页面。
- 源站应用层缓存:页面片段、数据库查询结果、整页静态化等。它决定回源时生成的内容是不是最新的,属于内部机制,但和 CDN 叠加起来会放大问题。
排查任何内容不更新的问题,都应该按这三层顺序查一遍,而不是先怀疑蜘蛛。
Cache-Control 怎么定比较稳
入口页和静态资源应该区别对待:
- 入口页 HTML:不建议设很长的 max-age。比较常见的做法是把 max-age 设得很短,几十秒到几分钟,或者用 no-cache,即允许缓存但每次要回源校验。真正需要每次都不一样时再用 no-store,但用多了会明显增加回源压力。
- CSS、JS、图片等静态资源:可以设长缓存,配合文件名里的版本号或哈希。这样蜘蛛抓入口页时不会因为资源拖慢整体响应。
- 接口和动态片段:一律短缓存或不缓存,避免不同入口页拿到串味的内容。
关键点是:入口页本身别做长时间不校验的缓存。宁可多回几次源,也不要让蜘蛛长期看到旧内容。
ETag 与 Last-Modified:304 是省事,也可能坑人
条件请求的价值在于:内容没变就返回 304,不传正文,省带宽也省源站 CPU。合理使用是好事,但有几个常见坑:
- 内容变了,标识没变:ETag 由文件修改时间或某些内部字段生成,改内容时没同步更新,结果蜘蛛拿着旧标识来校验,你回 304,蜘蛛就一直认为内容没变。
- 集群节点 ETag 不一致:多台机器生成的 ETag 不同,蜘蛛每次校验都像遇到新内容,反而可能增加抓取压力。此时不如统一用 Last-Modified,或者干脆关掉 ETag。
- 对 304 的误读:日志里全是 304,不代表蜘蛛没抓,只是没传正文。判断抓取是否正常,要看请求数、状态分布和内容版本的组合,不能只看正文体积。
内容更新后,怎么让新版本被看到
更新入口页之后,指望过一会儿蜘蛛自然会看到新版是碰运气。更稳妥的做法是:
- 更新源站内容,确认回源拿到的是新版本。
- 主动刷新 CDN 缓存,或等短 max-age 自然过期。
- 确认 ETag 与 Last-Modified 跟着变了。
- 用外部工具或本地请求验证边缘节点返回的是新内容。
- 再观察抓取日志中该路径的状态码和响应大小是否有变化。
几个反复出现的误区
- 全部 no-store 最安全:确实不容易看到旧内容,但回源压力会明显上升,蜘蛛集中来访时容易触发超时和 5xx,反而更糟。
- CDN 缓存越久越省钱:入口页恰恰是最不该长缓存的部分,省下的带宽可能换来一堆过期的抓取结果。
- 缓存不影响蜘蛛:影响很大,只是它作用在边缘节点和回源之间,你在源站日志里看不见。
- 304 多了就是被降权:304 说明内容没变,本身是正常交互,不必过度解读。
一个简单的检查清单
- 入口页 HTML:短 max-age 或 no-cache,允许校验。
- 静态资源:长缓存加版本化文件名。
- ETag 与 Last-Modified:生成规则稳定,多节点一致。
- CDN:入口页缓存规则单独配置,更新时有可用的刷新手段。
- 日志核对:能区分命中缓存、回源、304 三种情况。
缓存本身不会带来抓取,但配置不当会稳定地制造我明明改了的错觉。把它当成抓取链路上一个需要定期复核的环节,比事后到处找原因省事得多。