先取一个具体URL,用同一请求头分别保存原始HTML和渲染后的DOM,然后逐字段对比标题、正文、内链和状态码,差异集中在哪一层,就把排查范围缩到那一层,而不是直接改模板或全站重发。
选一个已经出现差异的页面,记录抓取时间、请求头、是否带Cookie、是否走CDN缓存,以及原始HTML的字节数。用curl取一次不执行脚本的响应,再用能执行JavaScript的渲染方式取一次最终DOM,两者都存成文件。这里的关键不是工具名称,而是保证两次请求的URL、UA和网络出口尽量一致,否则你比较的可能是缓存版本或地区差异,而不是静态与渲染的差别。
假设一个列表页原始HTML里有20条链接,渲染后只剩8条,且这8条都带rel="nofollow"。这个假设样本说明差异可能来自脚本对DOM的改写,而不是服务器返回了不同内容。下一步应查看脚本在哪一步移除或替换节点,而不是先怀疑robots.txt。
常见于前端框架把正文挂在客户端。此时先确认原始HTML里是否有可被解析的占位文本、JSON数据或<noscript>内容。若完全没有,抓取方是否执行脚本就决定了它能不能看到正文。对这类页面,优先考虑把关键内容改为服务端输出或预渲染,而不是只调整站点地图。
这类差异更隐蔽。原始HTML有标题和正文,脚本执行后却把标题替换成通用文案,或把内链改成按钮。此时要区分是脚本主动删除,还是渲染环境缺少接口数据导致回退。动作上,先禁用可疑脚本再取一次DOM,观察节点是否恢复;恢复则说明问题在脚本逻辑,不恢复则继续查数据接口和渲染超时。
例如原始HTML的canonical指向A,渲染后指向B;或原始HTML的状态码是200,渲染过程中接口返回404。这类差异不能只看最终DOM,要同时记录渲染过程中的网络请求和最终URL。若最终URL发生跳转,应把跳转链完整保存,再判断哪一步改变了可抓取对象。
不要因为一个样本成立就全站改版。先做一张对照表,至少包含:URL、原始HTML关键字段、渲染后关键字段、差异类型、是否影响内链、是否影响正文、是否影响canonical。若差异只出现在带查询参数的页面,而纯静态路径正常,处理范围就应限制在参数路由,而不是整站预渲染。
另一个可执行动作是:把同一模板下的10个URL按“有差异/无差异”各取5个,分别检查它们的脚本加载顺序和接口返回。若差异只出现在接口超时或返回空数组的样本上,那么问题更可能是渲染依赖外部数据,而不是模板本身。此时下一步应加超时兜底或服务端缓存,而不是删除脚本。
处理完一个样本后,用同一方法复查另一个模板的页面。若新样本的差异类型相同,才考虑把修复动作写成可复用的构建步骤;若类型不同,就保留为独立问题,不合并处理。
如果差异属于第一类,动作是让关键内容在原始HTML中可见,然后重新取一次静态响应,确认字段出现;确认后再检查内链是否可爬。如果属于第二类,动作是定位改写节点的脚本并加条件判断,改完后用同一请求头复测,观察被删字段是否恢复。如果属于第三类,动作是固定canonical和状态码来源,避免渲染过程改变最终URL。
每一步的结果都只回答一个问题:差异发生在内容生成、脚本改写还是请求链路。只有当前一步确认差异不再出现,才进入规模化验证;否则扩大样本只会把不同原因混在一起,让后续判断更困难。