蜘蛛打開一個入口頁,第一件事不是讀正文,而是讀响應头。正文寫得再規整,头信息里某個字段设错,蜘蛛對頁面的判断就可能完全變样。下面這几個字段,在蜘蛛池的日常维護里最容易被忽略,也最容易出問题。
Content-Type 與字符集:讀得懂,還是讀成乱碼
响應头里的 Content-Type: text/html; charset=utf-8 决定了蜘蛛用什么编碼去解碼字节流。如果頁面實际是 UTF-8,服務器却声明 gbk,蜘蛛按声明的编碼解碼,抓到的就是一堆問号和方块。虽然 HTML 里的 meta charset 也能声明编碼,但多數實現中响應头的優先級更高,两邊打架时以头為准。
维護建议很简單:让响應头和頁面里的 meta 声明保持一致,別一個 utf-8 一個 gbk 各说各话。改過服務器配置或換過 CDN 之後,這種情况尤其容易出現,值得定期核對一次。
Last-Modified 與 ETag:蜘蛛判断“變没變”的依據
蜘蛛再次来訪时,通常會带上 If-Modified-Since 或 If-None-Match,問服務器一句:内容變了没有?服務器回 304,蜘蛛就知道不用重新解析正文,节省双方的時間。
- 每次都輸出目前時間:程序图省事,把 Last-Modified 寫成請求發生的时刻。蜘蛛每次来都看到“刚刚更新過”,會認為頁面频繁變動,反复抓取,却拿不到實质新内容。
- 永遠返回一個很早的固定時間:蜘蛛認為頁面長期没動,重抓的意愿下降,新加的内容迟迟不被重新讀取。
- ETag 被中間层重寫:部分 CDN 或反代會把 ETag 換成自己生成的值,導致同一份内容在不同节点上 ETag 不一致,條件請求失效,等于每次都全量抓。
動態生成的入口頁,最好让 Last-Modified 跟随實际内容的時間戳,而不是跟随請求時間。
Cache-Control 與 Age:蜘蛛拿到的是不是最新版
Cache-Control 里的 max-age 设得很長,又叠了 CDN 缓存,蜘蛛抓到的可能是一份几小时甚至几天前的副本。响應头中的 Age 字段能直接告诉你:這份内容在缓存里已经放了多久。如果 Age 明顯偏大,而站点内容更新频繁,就要考虑對 HTML 類請求缩短缓存時間,或者做主動刷新。
X-Robots-Tag:藏在头里的指令
除了頁面里的 meta robots,HTTP 头里也能下發爬虫指令,寫法是 X-Robots-Tag,可以针對單個 URL、整個目錄,甚至某類文件類型生效。
它的麻烦之處在于隐蔽:網頁源碼里什么都看不出来,只有抓响應头才能發現。常见的坑是配置里给某個目錄批量加了 noindex,後来頁面挪了用途,指令還留着,于是入口頁内容正常、連結正常,却長期不進索引。
排查“内容没問题却不被索引”這類現象时,先看响應头,往往比翻正文更快找到答案。
Vary 與缓存分片:同一個 URL 的不同版本
如果响應头里寫了 Vary: User-Agent,缓存系統會按不同的 UA 分開存副本。對蜘蛛和普通訪客返回不同版本的站点,就會出現两邊看到的内容不一致的情况。有些站為了给爬虫减负,對爬虫返回精简頁面,本意是好的,但一旦精简版丢掉了主要連結或正文,效果就反過来了。建议至少做一次對照:用普通 UA 和蜘蛛 UA 各抓一次,比對正文和連結是否一致。
怎么快速自查
- 用命令行工具只取响應头,不要下载整個頁面,逐條看狀態碼、Content-Type、Last-Modified、ETag、Cache-Control、X-Robots-Tag。
- 換一個 UA 再抓一次,比對两次的头信息和正文長度是否一致。
- 隔一段時間重复抓同一 URL,观察 Last-Modified 與 ETag 是否稳定,304 是否按预期返回。
- 把结论记進站点维護清單,尤其是目錄級的 X-Robots-Tag 和缓存策略,交接时最容易漏。
响應头不是玄学,它只是蜘蛛進入頁面的第一道门。把這道门上的几個字段理顺,很多看起来莫名其妙的抓取異常,其實都會自己消失。