蜘蛛回訪时,先讀的是响應头
很多站点运营者把注意力放在頁面内容和連結上,却忽略了服務器返回的响應头。蜘蛛每次抓取一個 URL,除了拿到 HTML,還會讀一组头部字段,其中 Last-Modified、ETag、Cache-Control 直接影响它下一次要不要来、来的时候拿的是不是同一份内容。對蜘蛛池的入口頁来说,這種影响會被放大:入口頁數量多、更新频率不一,头部寫错很容易造成要么反复抓取、要么長期不抓。
Last-Modified:最直观的“上次改動時間”
它的作用是告诉蜘蛛這個頁面最後一次變化的時間。蜘蛛再次訪問时可能带上 If-Modified-Since 請求头,如果服務器判断内容没變,返回 304,蜘蛛就不必重新下载整頁。這能省下抓取预算,對入口頁數量多的站点是件好事。
容易寫错的地方
- 把 Last-Modified 寫成目前時間。每次請求都返回“刚刚修改”,蜘蛛會認為頁面一直在變。
- 批量生成的入口頁共用同一個時間戳,等于告诉蜘蛛這批頁面是同一次改動的,缺乏区分度。
- 頁面内容更新了,头部時間没跟着變,蜘蛛可能几周都不来取新版。
ETag:更细,也更容易被誤用
ETag 相当于内容指纹,蜘蛛用 If-None-Match 與它比對。問题在于:如果 ETag 是每次請求随机生成(比如按進程 ID、請求時間拼接),那么同一份内容每次返回的 ETag 都不一样,蜘蛛會判断内容每次都變,结果就是反复抓取一個根本没變的頁面。
ETag 的原則很简單:内容不變,值就不變;内容一變,值就必须變。做不到這一点,不如干脆不返回。
有些服務器會根據文件 inode 或部署時間生成 ETag,每次發布、扩容、換机器都會變,同样會造成無谓的回訪。
Cache-Control:蜘蛛不一定听,中間层一定听
搜尋引擎爬虫通常有自己的抓取节奏,不一定會嚴格按 Cache-Control 决定是否重抓。但 CDN、反向代理、负载均衡會嚴格遵守。也就是说,蜘蛛看到的是中間层给它的那一份。如果 CDN 缓存了一份舊的空白頁,或者缓存了 404 响應,蜘蛛拿到的東西和你在源站看到的完全不同。
常见的情况是:入口頁上线後改了内容,源站已经更新,CDN 還在返回几天前的版本,蜘蛛连續几次抓到的都是舊内容,于是降低了回訪频率。
三者怎么配合
- 内容型入口頁:给出真實的 Last-Modified,ETag 保持稳定,Cache-Control 設定合理的 max-age,让 CDN 承担大部分請求。
- 频繁更新的入口頁:max-age 不要太長,避免蜘蛛長期看到舊版本。
- 已下线頁面:返回 410 或 301,並让中間层不要繼續缓存舊的 200 响應。
- 批量模板頁:確認每個 URL 的头部是可预期的,不要出現随机 ETag。
用日誌做核對
- 看蜘蛛請求里是否出現了 If-Modified-Since 或 If-None-Match,說明缓存协商在正常工作。
- 統計 304 的比例。比例過低,可能是 Last-Modified 或 ETag 一直在變。
- 同一個 URL 连續抓取多次,對比返回的 ETag 是否一致。
- 換一個網絡位置請求,或直接回源,確認 CDN 返回的头部與源站一致。
几個常见誤区
- 以為把 max-age 设得很長就能让蜘蛛少来,實际上它只影响中間层,不影响蜘蛛自身的抓取策略。
- 以為 ETag 有没有都無所谓,随机 ETag 會造成明顯的重复抓取。
- 只检查首頁的响應头,忽略了入口頁、過渡頁可能由不同規則生成。
- 換了服務器或 CDN 之後没有重新核對头部,行為悄悄發生改變却没人察觉。
小结
响應头不是装饰。Last-Modified 说的是“什么时候變的”,ETag 说的是“變成了什么样”,Cache-Control 决定中間层能替源站回答多久。把這三件事對齐,蜘蛛拿到的版本才更接近你希望它看到的那一份,回訪节奏也更符合预期。检查频率不必很高,但每次上线、換机器、調 CDN 之後,都值得花几分钟確認一下。