搜索蜘蛛是按字节流读取页面的,状态码返回 200,并不等于内容被完整送出。如果连接在中途断开、压缩流没有正常结束,或者后端在超时后提前吐出半截 HTML,蜘蛛收到的就是一个“半成品”页面:头部正常、正文缺失、页脚的内链入口整体不见。这类问题不会在状态码统计里暴露,只会慢慢体现在 URL 发现变少、已收录页面内容长期不更新上。
截断的常见表现
- 同一 URL 多次抓取,日志里的响应字节数忽大忽小,最大最小值差距明显
- 页面正文只到某个栏目就结束,页脚导航、分页、相关阅读等入口整体消失
- 抓取耗时普遍贴近某个整数(如 30s、60s),像是被超时切断
- 返回体是空模板或“加载中”占位,状态码却仍是 200
- 蜘蛛抓取频次下降,新页面迟迟等不到首次抓取
先确认是不是真的被截断
不要只看状态码。在服务器访问日志里补充记录响应字节数和上游耗时,按 URL 分组对比:抓一份正常样本的字节数作为基线,再挑几个字节数偏低的 URL 用命令行复现,分别带和不带压缩请求头各取一次,比较实际写入的字节数、响应头中声明的长度与实际长度是否一致。
如果带压缩时明显偏短、不带压缩时正常,问题基本落在压缩层或传输层,而不是模板本身。
常见的几类成因
压缩与传输层不一致
响应头声明了长度但实际写入不足、分块传输缺少结束标记、压缩流被提前关闭,都会让客户端认为响应到此为止。CDN、反向代理与应用三层同时开启压缩时更容易出现这种情况。建议只在一层做压缩,并确认长度声明与实际内容一致。
后端超时后返回半截内容
模板渲染到一半、循环取数中断、流式输出被上游掐断,都可能产出“前半段正常、后半段缺失”的 HTML。这类响应状态码常常还是 200,比 5xx 更难发现。较稳妥的做法是:渲染失败时明确返回 5xx,或输出一个结构完整的兜底页面,而不是把残缺内容直接送出去。
代理与时序配置过紧
读取超时、缓冲关闭、连接空闲回收等参数设置过短,会让服务端在内容写完之前断开。观察被截断的 URL 是否集中在慢查询、大列表或依赖外部接口的页面上,如果是,优先压缩这几类页面的耗时,而不是一律放宽全局超时。
限流与连接重置
并发限制或防爬规则触发时,连接可能在写入部分响应后被重置,日志里常表现为同一 IP 段集中出现偏短的响应。核对限流阈值与蜘蛛抓取节奏是否冲突,必要时把已知搜索蜘蛛的抓取与其他流量分开处理。
建议的排查顺序
- 补齐日志字段:响应字节数、上游耗时、是否命中缓存。
- 按 URL 抽样,对比字节数基线与异常样本。
- 用带压缩与不带压缩两种方式复现,定位是压缩层还是应用层。
- 查看被截断页面的共性:数据量、外部依赖、模板复杂度。
- 检查代理超时、缓冲与压缩配置,只保留一层压缩。
- 修复后持续观察字节数分布与抓取回访频率,确认趋势稳定。
判断抓取是否健康,除了看状态码,还要看每一次响应是否完整交付。字节数是最容易被忽略、也最容易建立基线的一个指标。
修复后的观察重点
- 响应字节数集中在基线附近,异常样本占比下降
- 被截断页面尾部的内链重新出现在抓取日志中
- 慢页面耗时下降,抓取不再卡在超时边界
- 新提交的 URL 首次抓取时间趋于稳定
截断问题往往不是单点故障,而是超时、压缩、限流、模板兜底几处设置叠加的结果。按入口到后端逐层核对,先把“内容是否完整送达”这件事做扎实,URL 发现与内链传递才有意义。