做抓取分析时,很多人只看源站日誌,忽略了中間那一层。實际线上,蜘蛛的請求往往先到 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。
- 頁面内容确實變了再改時間戳,不要為了催抓取而频繁改動。
一份可以照着做的自查清單
- 用搜尋蜘蛛 UA 請求几個代表性 URL,记錄狀態碼與响應头。
- 看响應头里有没有缓存命中标记,例如各類 x-cache、age 字段。
- 绕過 CDN 直连源站請求同样 URL,對比 HTML 是否有差异。
- 在 CDN 後台查机器人报告,確認被拦截的請求里有没有搜尋蜘蛛。
- 在源站日誌里按蜘蛛 UA 統計狀態碼分布,403、429、5xx 的占比是否異常。
- 核對地域跳轉規則,確認蜘蛛不會被来回送往不同地址。
CDN 和缓存层本身並不决定一條 URL 能不能被抓到,但它决定了蜘蛛每次抓到的到底是什么。把這一层理顺,抓取日誌里的異常會少一大截,排查时也不用再在源站和邊缘之間来回猜。