bigywater.tech
爬虫工程 · 39

请求指纹:只哈希 URL 为什么会漏掉 POST 和请求头不同的请求

只用 URL 判断两个请求是不是同一个,在 GET 页面上通常够用。可一旦服务器按请求体、语言头或 Cookie 返回不同的内容,URL 相同的请求其实是不同的页面。这篇构造这样的服务器,看四种指纹方案各自漏掉多少。

62 对 131
只哈希 URL 与带上方法、请求体、关键请求头的指纹,各自拿到的不同内容数
69
只哈希 URL 时被当成重复丢掉的不同页面数
0 个多发
这四种方案多发的重复请求都是 0——代价只在漏抓

标准答案

实测 · 本机执行输出
  请求队列共 180 个:40 个商品页 × 2 种语言 = 80;POST /search 20 种请求体 × 重复 3 次 = 60;/account/ 10 个 URL × 2 种 Cookie = 20;/about 重复 10 次;GET /search?q= 10 个 = 10
  全部发一遍之后,服务器返回了 131 种不同的内容(真正重复的请求有 49 个)

180 个请求发一遍,服务器返回 131 种不同的内容。其中 49 个是真正的重复(/about 重复 10 次、POST 搜索每个重复 2 次等)。

四种指纹

实测 · 本机执行输出
  指纹方案                                     发出的请求       拿到的不同内容     漏掉的       多发的重复请求
  只哈希 URL                               62            62      69             0
  方法 + URL                              62            62      69             0
  方法 + URL + 请求体                        81            81      50             0
  方法 + URL + 请求体 + 关键请求头               131           131       0             0

只哈希 URL 或哈希“方法 + URL”只抓到 62 种,漏掉 69 种;加上请求体 81 种;再加上 Accept-Language 和 Cookie 才是 131 种,不漏也不多发。爬虫的指纹应当包含所有会影响响应的请求要素。

漏的是哪些

实测 · 本机执行输出
  account 带 Cookie:被当成重复丢掉、实际内容不同的请求 10 个
  product 带 Accept-Language:被当成重复丢掉、实际内容不同的请求 40 个
  search POST:被当成重复丢掉、实际内容不同的请求 19 个

URL 相同、Accept-Language 不同的 40 个商品页;URL 相同、Cookie 不同的 10 个账号页;URL 相同、请求体不同的 19 个 POST 搜索。这些在“只哈希 URL”的指纹下统统被当作重复,没有任何报错。

请求体规范化

实测 · 本机执行输出
  请求体 'q=word1&page=2' 与 'page=2&q=word1':服务器对两者返回的内容相同吗?True(对本服务器相同);按原始字节哈希的指纹相同吗?False;按解析后排序再哈希的指纹相同吗?True

请求体的参数顺序不同,按原始字节哈希会得到不同的指纹(多抓一次);解析后排序再哈希则相同。这只在服务器对参数顺序不敏感时才合理。把哪些请求头纳入指纹,是个取舍:纳入太多会让指纹碎片化(每个请求头都不同),太少则漏抓。

分步演示

请求指纹
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / requests 2.34.2 / aiohttp 3.14.3 / lxml 6.1.1(系统 Python);所有请求只发给本机自己起的测试服务器(127.0.0.1,端口 9960 以上,不访问任何真实网站);服务器可以按实验需要制造延迟、断连、压缩、重定向等行为,并记录收到的原始请求;计时用 time.perf_counter,数字每次运行会有小幅抖动。服务器按路径决定内容:商品页取决于 Accept-Language,/account 取决于 Cookie 里的 tier,/search 取决于请求方式和 q;请求队列是手工构造的 180 个请求;“标准答案”是把 180 个都发一遍后的不同内容数;指纹方案是纯 Python 函数,按指纹去重只发每个指纹的第一个请求
    • 没有验证:真实站点里请求头对内容的影响(User-Agent、Referer 等是否也该进指纹);Scrapy 的 request_fingerprint 具体包含哪些要素(没有安装);带 Cookie 的会话状态变化(登录之后同一个 URL 内容变了);指纹碎片化的量化;不同内容但语义等价的页面(近似去重,后面有 SimHash 一篇)
    京ICP备2026067502号-1京公网安备11010502063487号