这种差异通常不是robots.txt本身前后矛盾,而是抓取阶段与渲染阶段读取了不同的资源或规则。先确认差异发生在哪一步:是同一URL的原始HTML允许抓取、渲染后却被脚本改写成受限状态,还是静态文件与脚本注入的meta robots给出了相反指令。定位方法是把“抓取时看到的”和“渲染后得到的”分开记录,再逐项排除。
第一种解释是规则来源不同。robots.txt的Disallow作用在抓取调度层,而meta robots或X-Robots-Tag的noindex作用在索引层。如果静态HTML没有noindex,脚本执行后动态插入了<meta name="robots" content="noindex">,就会出现“抓取正常、索引结果相反”的表象。此时robots.txt并没有失效,只是它不负责移除索引。
第二种解释是渲染资源被拦截。脚本本身、接口数据或渲染所需的关键JS如果被robots.txt禁止抓取,渲染器拿不到完整DOM,只能看到静态骨架。于是静态响应里存在的链接或内容,在渲染结果中消失。反过来,如果静态响应被CDN或服务端缓存成旧版本,而脚本渲染出的是新版本,也会造成同一URL两种结果。
两种解释都成立的前提是:同一URL确实存在两套可观察输出。若只有一套输出,问题更可能出在查看工具或缓存,而不是规则冲突。
第一组证据是请求日志与渲染日志的时间戳。若robots.txt的抓取请求返回200且内容完整,但渲染队列里同一URL的脚本资源请求返回403或404,则支持“渲染资源被拦截”。若脚本资源全部200,而渲染后的DOM里出现noindex,则支持“规则来源不同”。
第二组证据是禁用脚本后的原始响应。用抓取工具或浏览器开发者工具关闭JavaScript,直接查看HTML源码。如果源码中已有noindex而脚本又把它删除,说明静态层与脚本层的指令方向相反;如果源码中没有noindex,只有渲染后才出现,说明是脚本注入。
第三组证据是robots.txt的User-Agent分组。不同抓取器可能匹配到不同规则组。假设一个站点为通用抓取器写了Disallow: /api/,却没有为渲染器单独放行,那么渲染器取不到接口数据,静态响应与渲染结果自然不同。核对时要把实际请求的User-Agent与robots.txt中的分组逐条比对,而不是只看文件开头。
meta name="robots"和X-Robots-Tag,记录指令值。完成第2步后,如果发现静态层允许、渲染层禁止,下一步应优先修改脚本注入逻辑,而不是改robots.txt。因为robots.txt无法覆盖脚本运行时才出现的meta指令。完成第4步后,如果发现渲染资源被Disallow,下一步应针对渲染用User-Agent放行必要路径,同时保留对无关路径的限制。
假设某列表页静态HTML包含20条链接,脚本渲染后只显示5条,并插入noindex。排查发现robots.txt禁止了/api/list,而脚本依赖该接口补全剩余15条。此时差异原因不是robots协议写错,而是抓取限制切断了渲染数据源。修正方式是允许渲染器抓取该接口,或把列表数据改为服务端输出。动作改变后,重新对比静态与渲染结果,若两者链接数量和meta指令一致,说明差异已收敛到可解释范围。
需要留意,robots.txt的抓取限制不等于可靠的索引移除。即使脚本渲染后出现noindex,已索引的URL也不会因为一次抓取限制而立即消失。站点地图也不保证收录,HTTPS同样不保证排名。不同搜索引擎对脚本渲染和meta指令的支持情况须分别核查,不能把一次对比结果直接推广到所有抓取器。
把静态响应、渲染结果、robots.txt分组和缓存头四份证据放在同一时间线上核对,就能判断差异是规则来源不同还是渲染资源被拦截,并据此决定改脚本、改robots.txt还是改缓存策略。