同一份正文分别用 200 OK 和 304 Not Modified 返回时,抓取工具对“这一轮是否拿到了新内容”的判断会不同;若用 200 与 410 Gone 对比,则连“这个地址还应不应该存在”都会改变。因此,响应头不是收录的装饰项,而是决定后续动作的输入信号。
假设某站有两个地址 A 和 B,正文完全一致,区别只在响应头:A 返回 200 OK 和正常长度,B 返回 304 Not Modified,但页面正文在浏览器里看起来一样。此时如果只凭“内容相同”就判断两者等价,可能会漏掉一个事实:304 通常表示客户端带着缓存验证条件来请求,服务器认为缓存仍然可用,而不是每次重新下发完整正文。抓取工具若没有对应的缓存验证条件,看到的响应行为可能不同。下一步不是立刻删掉 B,而是先确认 B 在无缓存条件下返回什么。这个动作会直接影响判断:如果无缓存时 B 也返回完整正文,那它更像普通重复地址;如果 B 始终依赖验证头才给正文,就要先解决可重复抓取的问题。
把响应头分成两组看,判断会清楚很多。
200、304、206 主要影响“这次拿到了多少、是否完整”。正文相同不代表抓取记录相同。301、302、404、410、503 影响“这个地址还应不应该被继续访问”。其中 410 比 404 更明确地表达资源已移除,但两者都不等于自动从索引中消失。Content-Type、Content-Encoding、Vary 影响解析和缓存分流。正文相同但 Content-Type 不同,可能让同一段文字被当成不同资源处理。所以,页面内容相同但响应头不同时,先问自己:我要判断的是“这一轮抓取是否完整”,还是“这个地址是否还值得保留”?两个问题对应不同证据,不能混在一张清单里。
假设你确认 A 和 B 正文一致,且都能稳定返回完整内容。此时有两种做法:
304 或空正文。这里的关键不是“哪个做法更正确”,而是先确认响应头是否稳定。若 B 在无缓存条件下也返回完整正文,保留双地址并用等价信号收敛是可接受的;若 B 只在带验证头时返回 304,那它不适合作为独立可抓取地址保留,应优先让 B 稳定返回完整正文或直接重定向。
下面这些差异经常被忽略,但会改变判断:
Vary 指向 User-Agent 或 Accept-Encoding 时,同一地址对不同请求方可能返回不同正文或不同编码。正文相同只是你当前看到的那一次相同。Content-Length 与实际正文长度不一致时,抓取工具可能截断或重试。此时“内容相同”可能只是你本地浏览器渲染后的结果。Cache-Control 与 Expires 决定中间缓存是否直接返回旧响应。旧响应里的正文可能仍是同一份,但响应头已经过期,后续判断会分叉。X-Robots-Tag 放在响应头里时,作用范围可能覆盖整条响应,而不只是 HTML 里的 meta 标签。正文相同不代表指令相同。这些差异不会单独证明某个地址应该被移除,也不能仅凭一次抓取就断定处理正确。更稳妥的做法是:固定一种请求条件,记录响应头与正文摘要,再换一种条件重复一次,看差异是否稳定出现。
面对“内容相同、响应头不同”的两个地址,可以按下面顺序走:
Content-Type、Content-Length 和正文摘要。304 或空正文,先解决它能否稳定返回完整正文;在解决之前,不要把它当作可独立保留的地址。Vary、Cache-Control 和 X-Robots-Tag 是否不同。若不同,先统一这些头,再决定保留还是收敛。这个顺序的核心是:先让响应头可重复,再谈内容等价。否则你看到的“内容相同”可能只是某一次请求的偶然结果,后续动作就会建立在错误前提上。