先看死链处理配置是否依赖客户端脚本:如果服务器对失效URL返回410或301,而浏览器执行脚本后又把页面改成200或跳转到首页,差异根源通常在“响应层”和“渲染层”各说各话。定位时先固定一个失效URL,分别记录原始HTTP状态、最终渲染后的DOM状态和跳转链,再判断该以哪一层为准。
静态响应指服务器直接返回的状态码、响应头和响应体;脚本渲染结果指浏览器执行JavaScript后,DOM里出现的链接、跳转或内容。两者不同,不等于死链处理一定失败,也不等于一定成功。要先把证据拆开:
curl -I或等效方式查看原始响应码和Location头,确认服务器层是否已对失效URL做处理。<a>是否仍存在,以及它们的href是否被脚本改写。如果原始响应是410,而脚本把页面内容替换成正常栏目页,那么对用户可见的结果与对爬虫可见的响应层结果可能不一致。下一步不是立刻改配置,而是确认这种不一致是否由你的模板、前端路由或第三方脚本引入。
当原始响应已经返回410或301,脚本只是把空页面替换成“内容已迁移”提示或推荐入口,这种差异通常可以接受。判断依据是:失效URL没有返回200,且跳转目标与死链处理策略一致。
此时应做的动作是检查脚本兜底是否干扰了状态码。有些前端框架在客户端路由中会把不存在的路径渲染成200页面,即使服务器最初返回410。结果就是:用户看到友好提示,爬虫却可能拿到200,导致失效URL被当作有效页面继续保留。下一步应让服务器层继续返回正确状态码,而不是用脚本把410改成200。
例外是:如果这个URL本身是应用内路由,服务器无法预知所有路径,只能先返回200再由脚本判断。此时需要为失效路由单独设计服务端返回规则,不能只靠客户端脚本兜底。
如果原始响应是200或404,而脚本执行后把页面跳转到首页、栏目页或搜索页,这说明死链处理主要发生在客户端。对用户来说可能“看起来正常”,但对抓取和索引来说,原始响应仍是关键证据。
定位动作:先抓取该URL的原始响应,再抓取脚本跳转后的最终URL,比较两者的状态码和内容。若原始响应是404,最终URL是200,说明脚本跳转改变了可见结果,但原始失效信号仍然存在。此时应决定:
假设一个站点把旧产品页全部交给前端路由处理,服务器对所有/product/*都返回200。脚本发现产品不存在后跳转到首页。此时原始响应是200,最终渲染也是200,但中间发生了客户端跳转。对用户而言是“首页”,对爬虫而言可能仍是一个200的旧产品URL。这个假设说明:只看最终渲染结果会漏掉原始响应层的问题。
要减少争议,按固定顺序记录同一失效URL在四个节点的结果:
Location头。如果节点一和节点三不同,先判断差异是否由脚本跳转、前端路由或第三方组件造成。若节点一已返回410,节点三却显示200,优先修脚本或路由,不要只改内容。若节点一返回200,节点三跳转到410页面,则要检查脚本跳转是否被爬虫执行;多数情况下,服务器层应直接返回410,而不是依赖脚本。
还要注意:robots.txt的抓取限制不等于可靠的索引移除,站点地图也不保证收录。若你用robots.txt屏蔽失效URL,同时脚本又把它渲染成200,两者会互相干扰。此时应分别核查搜索引擎支持情况,不要假设所有引擎都会按同一方式处理。
可以保留差异的条件是:服务器层已返回正确状态码,脚本只做用户体验增强,且不会把410或301改写成200。必须统一的条件是:原始响应为200,脚本跳转后才出现死链处理结果;或者原始响应为410,脚本又把页面变成200。后一种情况会让失效URL继续以有效页面参与抓取和索引判断。
实际动作上,先为失效URL建立一张对照表:原始状态码、最终状态码、跳转目标、脚本是否改写链接。若原始状态码与最终状态码不一致,先修服务器层;若一致但链接来源仍指向失效URL,再修内链和站点地图。这个顺序会影响下一步:服务器层未定时,改内链只是减少入口,不能替代对失效URL本身的响应处理。