爬虫拿到一個 URL 之後,最先判断的通常不是頁面寫了什么,而是服務器返回了哪個狀態碼。狀態碼决定這次請求算不算一次有效抓取、這個地址之後還會不會被再次訪問、抓取预算要不要繼續投给它。入口頁數量一多,狀態碼管理的好坏就會直接反映在訪問日誌的分布里。
狀態碼是爬虫的第一次判定
頁面正文要下载完才能解析,狀態碼在响應头里就已经给出。對爬虫来说,這是一個成本极低的判断依據:200 意味着可以繼續讀下去,4xx 意味着這個地址目前没有内容,5xx 意味着服務器這邊出了問题、可以稍後再来。入口頁如果長期返回混乱的狀態碼,爬虫對這個域名的抓取节奏就會變得保守。
200:不是返回成功就算合格
200 只代表請求被正常處理,不代表頁面有抓取價值。以下几種情况都属于“狀態碼没错、但抓取被浪費”:
- 返回 200,但正文為空,只剩導航、頁脚和模板占位;
- 返回 200,内容與入口頁主题無關,等于把抓取引向無效頁面;
- 返回 200,可见内容依赖 JS 渲染,而爬虫拿到的是空壳 HTML。
這類頁面在日誌里顯示為成功,在效果上却接近失敗,通常被称為软 404。它比明确的 404 更麻烦,因為爬虫會反复回来確認,而每次確認都在消耗同一份预算。
404 與 410:確認不再需要时怎么選
404 表示目前找不到该资源,410 表示已经永久移除。如果入口頁只是临时下线做調整,用 404 會让爬虫在之後一段時間内反复重试;如果确實不再使用,410 表達得更明确,重复訪問通常會更快减少。選擇哪一種,标准是這個地址還會不會回来,而不是哪個“看起来更狠”。
503 與 429:临时狀態的正确用法
维護、迁移、流量異常时,503 是比 404 更合适的表達,配合 Retry-After 告诉爬虫多久之後再来。但要避免把 503 当成長期挡板:長時間返回 503,爬虫會逐步降低訪問频率,恢复後需要一段時間才能回到原来的抓取节奏。429 則用于請求過于频繁的场景,同样建议带上等待時間,而不是無提示地拒绝。
跳轉狀態碼:301 與 302 的分工
301 表示永久轉移,302 表示临时轉移。入口頁之間如果大量使用跳轉,每次抓取都要多消耗一跳請求;跳轉鏈堆到两三层以上,抓取深度和到達率都會受影响。能用直鏈的地方尽量用直鏈,跳轉留给确實發生地址變更的场景。
上线前的狀態碼检查清單
- 入口頁是否都返回 200,且响應中带有可见正文,而不是空壳;
- 已下线的頁面是按實际意图返回 404 還是 410,有没有長期挂着的假 200;
- 维護期的 503 是否带有 Retry-After,有没有一挂就是几周;
- 跳轉鏈是否控制在一层,是否存在 A 跳 B、B 又跳回 A 的循环;
- 日誌中狀態碼分布是否稳定,5xx 比例是否出現異常抬升。
狀態碼本身不會让站点立刻出問题,但長期、大量、杂乱的狀態碼,會让爬虫逐渐降低對這個域名的抓取意愿。把狀態碼当成入口頁的一項基础配置来维護,比事後從日誌里找原因要省力得多。