搜尋抓取

CDN 缓存與抓取:蜘蛛每次拿到的是哪一份 HTML

蜘蛛的請求通常先到 CDN 或反向代理,命中缓存就直接返回,不一定回源。缓存键、Vary 头、邊缘机器人規則、地域跳轉和缓存過期策略,都會影响蜘蛛最终拿到的頁面版本。本文梳理這一层常见的几處變量,並给出一份可执行的自查清單。

搜尋抓取

CDN 缓存與抓取:蜘蛛每次拿到的是哪一份 HTML

做抓取分析时,很多人只看源站日誌,忽略了中間那一层。實际线上,蜘蛛的請求往往先到 CDN 或反向代理,命中缓存就直接返回,不一定回源。于是“蜘蛛抓到了什么”取决于邊缘节点怎么配置缓存键、怎么识別爬虫、怎么處理地域與實驗分流。這几處任何一個設定不当,都可能在源站日誌里留下一串 200,但蜘蛛拿到的頁面跟用戶看到的並不一样。

蜘蛛的一次請求會经過哪几层

  • DNS 解析:站点域名 CNAME 指向 CDN,蜘蛛拿到的是邊缘节点 IP,不是源站 IP。
  • 邊缘节点:判断缓存是否命中,命中則直接返回,未命中才回源。
  • 回源鏈路:源站返回 HTML,邊缘按規則决定缓存多久、缓存成什么键。
  • 响應返回:狀態碼、响應头和 HTML 一起回给蜘蛛。

這四层里,通常只有第三层是你平时調试时打開的那台机器。

缓存键與 Vary:同一個 URL 可能存着几份 HTML

缓存键一般由 URL 加若干請求头组成。如果邊缘把 User-Agent 算進缓存键(常见于配置了 Vary: User-Agent 的场景),搜尋蜘蛛的 UA 和普通浏览器 UA 就會命中两個不同的缓存對象。這本身不算错,問题在于两份缓存可能来自不同時間的回源,蜘蛛拿到的那份可能比用戶看到的更舊。

移動與桌面两套模板时更麻烦。如果邊缘按 UA 分流模板,而蜘蛛的移動版 UA 又被誤判成桌面,回源就會走错分支。

  • 尽量让同一 URL 在不同 UA 下返回同一份 HTML,渲染差异交给 CSS 或前端處理。
  • 确需按 UA 分流时,把已知搜尋蜘蛛單獨列一组規則,明确它走哪套模板。
  • 检查缓存键是否混入了 Cookie、語言、设备等變量,避免缓存被切成大量碎片,命中率骤降。

邊缘上的机器人規則:別無声地把蜘蛛拦掉

不少 CDN 與安全产品預設開啟机器人防護、速率限制或 JS 挑战。對普通爬虫這是好事,但搜尋蜘蛛可能被一起拦下。表現通常是 403、429,或者一個需要执行 JS 的挑战頁。蜘蛛拿到挑战頁,這條 URL 這次抓取基本白跑。

驗證方法不复杂:用 curl 带上搜尋蜘蛛 UA 請求首頁、列表頁、詳情頁各几條,看返回的是真實 HTML 還是拦截頁,再和普通 UA 的返回做對比。

規則上可以做分层:放行已知搜尋蜘蛛(最好通過反向解析確認不是伪造 UA),對匿名高频請求做限速,而不是一刀切。

地域重定向與 A/B 測試

有些站点在邊缘按 IP 國家或 Cookie 做跳轉,把訪客送到對應語言版本。如果蜘蛛從某個区域节点訪問,可能被跳到語言站 A;換一個节点,又跳到語言站 B。结果同一批 URL 在蜘蛛那里反复換地址,抓取路径變得不稳定。

A/B 測試同理。邊缘把一部分用戶分流到 B 版本,如果蜘蛛也被分進去,它看到的頁面和多數用戶不同,内容判断容易出偏差。一般做法是對搜尋蜘蛛固定走主版本。

缓存過期與條件請求

邊缘缓存到期後,回源會带上 If-Modified-Since 或 If-None-Match。源站正常返回 304 时,邊缘可以繼續用舊副本,蜘蛛也省一次传輸。但如果源站每次都對蜘蛛返回 200 全量 HTML,或者邊缘把 304 改寫成 200 加空 body,抓取開销就會被放大。

  • 確認源站的 Last-Modified、ETag 能透传到邊缘這一层。
  • 確認邊缘不會把 304 變成 200。
  • 頁面内容确實變了再改時間戳,不要為了催抓取而频繁改動。

一份可以照着做的自查清單

  1. 用搜尋蜘蛛 UA 請求几個代表性 URL,记錄狀態碼與响應头。
  2. 看响應头里有没有缓存命中标记,例如各類 x-cache、age 字段。
  3. 绕過 CDN 直连源站請求同样 URL,對比 HTML 是否有差异。
  4. 在 CDN 後台查机器人报告,確認被拦截的請求里有没有搜尋蜘蛛。
  5. 在源站日誌里按蜘蛛 UA 統計狀態碼分布,403、429、5xx 的占比是否異常。
  6. 核對地域跳轉規則,確認蜘蛛不會被来回送往不同地址。

CDN 和缓存层本身並不决定一條 URL 能不能被抓到,但它决定了蜘蛛每次抓到的到底是什么。把這一层理顺,抓取日誌里的異常會少一大截,排查时也不用再在源站和邊缘之間来回猜。