蜘蛛池知识

蜘蛛池與缓存层:爬虫抓到的入口頁,是谁给的那一版

入口頁前面挂了 CDN 或頁面缓存时,爬虫請求到的 HTML 未必是源站刚生成的那一版。本文讲清几種缓存形態對抓取结果的影响、几個關键响應头的含义、多节点版本不一致的常见成因,以及入口頁批量更新时该怎么刷新缓存、TTL 怎么设更合适。

蜘蛛池知识

蜘蛛池與缓存层:爬虫抓到的入口頁,是谁给的那一版

做蜘蛛池的人,注意力大多放在入口頁的内容差异、互鏈结构和數量規划上,却容易忽略一個更底层的問题:爬虫請求那個 URL 时,返回的 HTML 到底是谁生成的。如果入口頁前面挂了 CDN、反向代理或者頁面缓存,爬虫拿到的很可能不是你以為的那一版。

為什么缓存會改變抓取结果

爬虫是按 URL 取頁面的。中間只要存在缓存层,返回内容就可能来自缓存副本,而不是源站實时渲染的结果。對蜘蛛池来说,入口頁通常是批量生成、批量調整的,模板、锚文本、内鏈指向可能一天改好几轮。一旦缓存 TTL 设得很長,爬虫今天、明天、一周之後看到的都是同一份快照,你在源站做的更新動作等于打折执行。

更麻烦的是,缓存本身不是错誤配置,它在正常场景下就是提升响應速度的手段。問题在于入口頁的更新节奏,和缓存的有效期不匹配。

三種缓存形態,影响程度不一样

  • 浏览器缓存:主要影响真實用戶,對爬虫的影响相對小,因為爬虫往往不带本地缓存。但如果响應头寫成强缓存,某些抓取工具复用连接时也可能讀到舊内容。
  • 邊缘节点缓存:影响最大。回源频率由节点决定,各地节点回源時間点不同,就可能出現同一個 URL 在不同节点上是不同版本。
  • 服務端頁面缓存或對象缓存:源站内部先缓存一份渲染结果,只要缓存键设計不合理,入口頁之間的差异内容可能被串用,出現 A 頁顯示 B 頁锚文本的情况。

真正影响爬虫的那几個响應头

  • Cache-Control:重点看 max-age、s-maxage、no-cache、no-store、private。s-maxage 决定共享缓存(含 CDN)的有效期,常被忽略。
  • Expires:老式寫法,和 Cache-Control 同时存在时以 Cache-Control 為准,但两邊冲突會让人誤判。
  • ETag 與 Last-Modified:用于條件請求,能让回源變轻,但對内容是否為最新没有保證。
  • Vary:寫成 Vary: User-Agent 时,不同 UA 會被分配到不同缓存副本,入口頁内容一致性很难保證。
  • Age 與命中标记:Age 大于 0 基本可以判断這次返回来自缓存,排查时比看内容更直接。

同一 URL,不同节点版本不一致

入口頁批量更新後,如果没有主動刷新,常见現象是:一部分节点已经回源拿到新版本,另一部分還在提供舊版本。爬虫從不同出口 IP 請求,就有可能交替拿到新舊两份内容。表現出来就是抓取记錄不连贯、锚文本對不上、頁面摘要前後矛盾。

如果入口頁需要保持内容一致,這類情况比單纯的内容陈舊更难排查,因為源站自己测是正常的。

入口頁更新與缓存刷新的配合

  1. 入口頁單獨一套缓存策略,不要和目标頁共用同一组規則。
  2. 批量生成或批量改模板後,主動按路径刷新,而不是等 TTL 自然過期。
  3. TTL 建议從短開始,比如几分钟到几小时,观察回源压力和抓取情况再决定是否放宽。
  4. 需要在更新後马上被讀到的内容,用短 TTL 加主動刷新组合,比把 TTL 全關掉更稳。

一個常用排查流程

  1. 用 curl -I 直接看响應头里的 Age 和命中标记,先確認是否命中缓存。
  2. 換不同 UA、不同出口 IP 請求同一個 URL,對比返回内容與 Age。
  3. 检查是否有 Vary: User-Agent 這類容易造成多副本的寫法。
  4. 對比源站直连返回内容與节点返回内容,定位差异發生在哪一层。
常见誤区:以為改了源站内容,爬虫下次来就一定能看到。實际决定權在缓存策略和刷新動作上,源站改了但缓存没動,爬虫看到的仍然是舊版本。

几点落地建议

  • 不要把缓存键里塞入随机參數,否則每個 URL 都是獨立副本,既失去缓存意义,也让爬虫反复請求相同内容。
  • 入口頁的更新動作和缓存刷新動作,尽量在同一個流程里完成,避免只有一邊执行。
  • 如果入口頁需要長期稳定不變,可以放宽 TTL;如果需要频繁調整,就保持短 TTL。
  • 缓存命中带来的响應速度提升,對抓取节奏是正向的,但内容陈舊會削弱爬虫再訪的意愿,两者要一起權衡。

缓存不是收錄的開關,但它會让你的更新動作打折扣。把缓存策略和入口頁的更新节奏對齐,往往是投入最小、见效最直接的一步。