入口頁返回 200,抓取日誌里也确實有蜘蛛来過,但過一段時間去核對,發現蜘蛛拿到的正文要么是乱碼,要么干脆是空的。這種情况在批量铺入口頁时並不少见,問题往往不在蜘蛛,而在頁面自己交出去的東西。
先把“空”拆成几類
在動手之前,先要把“蜘蛛没讀到内容”分成几類,否則容易在错誤的方向上反复調整:
- 字节是空的:HTML 的 body 里没有可见文字,或者只剩一個容器标簽。
- 字节有内容但讀不懂:頁面輸出了中文,但编碼声明與實际字节不一致,呈現為問号或方块。
- 文字在图片里:内容以图片形式展示,HTML 中只有 img 标簽。
- 文字由脚本寫入:初始 HTML 是空壳,正文靠 JS 渲染後才插入。
這四類的成因和處理方式完全不同,先判断清楚,再去改,能省掉很多無效操作。
编碼声明與實际字节不一致
這是最常见的一類。典型表現是:响應头里寫着 Content-Type: text/html; charset=gbk,而頁面 meta 里寫的是 charset=utf-8;或者反過来。当两者冲突时,蜘蛛通常以响應头為准,于是同一份字节被按错誤的字符集解碼,中文就成了乱碼。
還有一種更隐蔽的情况:程序连接資料库时使用了 latin1 之類的字符集,中文在寫入阶段就已经被轉成了問号,頁面上看起来只是“文字怪怪的”,其實原始内容早就丢了。
自查方式很直接:带上响應头抓一次,再用十六進制工具看正文開头的几百個字节。如果服務器發出的是 GBK 字节流,而响應头声明 UTF-8,乱碼現象基本就能對上。
模板變量和循环輸出没被替換
批量生成的入口頁,常见問题出在模板层。占位符没有被替換,頁面直接把 {title}、{{content}} 這類标记渲染了出来;或者列表循环為空,頁面上只留下一個空的 ul 容器,正文区域一片空白。
這類問题的排查点有三個:模板引擎是否跑完、資料源是否取到记錄、缓存是否把未渲染完成的頁面存了下来。尤其是第三種,静態化任務中途失敗,缓存里留下的就是半成品頁面,蜘蛛抓到的正是它。
文字被放進了图片或画布
為了让頁面看起来整齐,有些入口頁把介绍文字直接做成图片,HTML 中只留一個 img 标簽。蜘蛛能拿到图片地址,但拿不到文字内容。如果确實需要图片,至少要保留一段文字說明,並把图片的 alt 属性寫清楚。
一份可执行的自查顺序
- 抓取响應头,確認 Content-Type 與 charset 声明。
- 抓取正文,看前 1KB 字节,比對编碼是否與声明一致。
- 關閉 JS 再抓一次,看初始 HTML 里有没有正文。
- 检查是否残留未替換的模板占位符。
- 检查循环輸出為空时,頁面是否退化成空白。
- 抽查多個入口頁,而不是只看首頁。
入口頁的作用是把蜘蛛带到下游,如果它本身就是一堵空白墙,蜘蛛走進去也带不走任何线索。编碼和渲染這類問题不顯眼,却會直接影响入口頁能不能被讀懂。