很多人排查蜘蛛池入口頁的抓取問题时,注意力都放在狀態碼、頁面内容和跳轉上,很少去看响應头。實际上,蜘蛛拿到一個 URL 之後,最先解析的就是响應行和响應头,頁面正文要等這一步之後才會被處理。响應头里寫错了東西,頁面本身再正常也可能白搭。
狀態碼之外,响應头决定了蜘蛛怎么理解這個頁面
200 只表示請求成功,它不說明返回的是什么類型的内容、能不能索引、要不要缓存,這些信息都在响應头里。入口頁通常是程序批量生成的,如果程序模板里带了某些預設头,几百上千個頁面就會一起带上,問题也會被一起放大。
几類值得逐項检查的响應头
Content-Type 與字符集
Content-Type 應该明确寫成 text/html 並带上字符集,例如 text/html; charset=utf-8。如果服務器返回 text/plain 或者干脆不寫,蜘蛛可能不按 HTML 去解析,頁面里的連結也就無法被提取出来。字符集寫错則會让中文變成乱碼,正文解析出一堆無意义的字符。
X-Robots-Tag
這是放在 HTTP 头里的指令,作用和頁面里的 meta robots 類似,但優先級更高。常见的誤用是:入口頁本身想被蜘蛛抓取,却因為服務器统一加了 X-Robots-Tag: noindex,導致頁面抓得到却不會進入索引。
抓取和收錄是两件事。noindex 不影响蜘蛛来抓,但會阻止頁面進入索引。如果你本来就只希望入口頁承担“被爬到、再顺着連結走到目标頁”的作用,那么 noindex 本身未必是错,但要清楚自己在做什么,而不是全局一刀切。
Server 與版本信息
Server 头會暴露服務器软件和版本号,比如 nginx/1.18.0。這不是抓取层面的問题,但從运维角度看,公開精确版本号没有什么好處,可以简化成 nginx 一類,或者用配置去掉。顺带检查有没有暴露内部轉發信息,比如上游地址、内網 IP。
Location 與跳轉
如果入口頁需要跳轉到目标頁,用的是 301 或 302,那么 Location 里的地址必须是完整的绝對 URL,且不能跳到自己、不能形成循环。相對地址、带空格未编碼的地址、跳轉鏈條過長,都會让蜘蛛在中間放弃。
缓存與校驗類头
Cache-Control、ETag、Last-Modified、Expires 這几項會影响蜘蛛重复訪問时的行為。入口頁内容長期不變,可以让蜘蛛用 If-Modified-Since 只拿到 304,省下带宽;但如果你希望蜘蛛每次重新解析頁面上的連結,缓存時間就不要设得太長。這類設定没有统一答案,取决于入口頁是静態展示還是频繁更新。
Content-Length 與實际内容
這個头如果和實际字节數對不上,通常意味着程序在中途出错,或者用了压缩但没有正确處理。蜘蛛可能讀到半截内容就断開,表現出来就是抓取不完整、頁面大小異常。
几個常见的配置坑
- 只在部分頁面上寫了正确的 Content-Type,其余走服務器預設值,而預設值並不是 HTML。
- 用反向代理或 CDN 回源时把源站头部改寫掉,或者叠加出两個 Content-Type。
- 為了防采集加了一堆自定义头,其中某個與蜘蛛的解析逻辑冲突。
- 跳轉配置寫在應用层,但响應头里的 Location 指向了測試环境地址。
- 頁面引用了 http 资源,却没有意识到混合内容對抓取和渲染的影响。
怎么查:curl 加日誌两步
最直接的方式是用 curl 看响應头,把 UA 換成你關心的爬虫,多测几個不同路径的入口頁,看看头部是否一致。如果服務器對爬虫和普通用戶返回不同的头,這一步就能看出来。
第二步是看訪問日誌。日誌里记錄的狀態碼、返回字节數和响應時間,可以和 curl 的结果互相印證。如果某個入口頁在日誌里反复出現 200 但字节數為 0 或极小,多半不是内容問题,而是响應头或程序輸出有問题。
小结
响應头不需要天天盯,但在入口頁上线之前、以及抓取表現異常的时候,值得花十几分钟逐項過一遍。它属于那種平时不出声、出問题很难查的配置,提前把模板規范好,比事後一個個补要省事得多。