先从一种普遍做法说起
好多人拿到服务商给的AB页跳转规则模板,第一反应就是把知道的云厂商IP段、机房IP、数据中心ASN全塞进黑名单里。乍一看挺合理——平台审核爬虫不都跑在云服务器上吗,真实用户用的是家宽和移动网络,把机房IP全拦了不就完事了。2016年前后这套确实管用,但搁现在这个对抗环境里,这么干会同时惹出两个麻烦:一边把大量走云代理出口的真实访客给误杀了,另一边那些从住宅代理池发出来的爬虫请求压根拦不住。说到底,IP这个维度的可伪装性已经高到没法单独拿来当判断依据了,爬虫伪装的重心早就从网络层挪到了浏览器指纹层和运行环境层。
AB页跳转的风险图谱要单独把爬虫伪装和模拟器特征识别拆成两个节点来讲,是因为这俩走的是完全不同的对抗路子:一个是平台爬虫拼命装成正常浏览器,另一个是平台爬虫用自动化浏览器引擎时怎么都会漏出来的模拟器痕迹。前者讲的是伪装能做到多像,后者讲的是模拟器本身有多容易露馅。这俩叠一块儿,就是AB页跳转规则误判率的主要来源。
输入阶段:哪些信号参与爬虫伪装判定
AB页跳转系统每次收到请求,会从三个层面采信号:请求头、TCP/TLS指纹、JavaScript执行结果。爬虫伪装要干的活儿,就是让这三个层面的信号尽量同时往真实浏览器那边靠。 User-Agent是最容易伪造的,权重也最低。真正有区分度的是头部字段的完整性和排列顺序。主流浏览器对Accept、Accept-Language、Accept-Encoding、Sec-Fetch这一串字段的排列有固定习惯,但很多伪装脚本只把User-Agent字符串换了,剩下的头部还是HTTP客户端库的默认样式。一个特别典型的暴露点是Sec-Fetch-Headers和Sec-Fetch-Site字段——要么干脆没有,要么取值跟当前请求上下文对不上。真实浏览器做跨站跳转的时候这些字段是自动带的,脚本化请求经常整个缺失。
TCP层的指纹包括初始窗口大小、TTL值、TCP选项的排列顺序,TLS层主要看Client Hello报文里的密码套件顺序、扩展列表和椭圆曲线组。这些东西不是脚本开发者随手能改的,是底层网络栈决定的。爬虫要伪装到这个深度,一般得借助特定语言运行时或者改过的网络库才能复现目标浏览器的指纹。AB页跳转系统如果只做HTTP层检测、不比对TLS指纹,会漏掉一大类爬虫伪装。
JavaScript执行环境信号
请求进来之后,跳转系统在页面里注入检测脚本,读navigator对象、window对象属性、canvas渲染结果。爬虫伪装在这一层要面对的是工程量指数级往上翻的问题:navigator.platform、navigator.maxTouchPoints、screen.colorDepth、devicePixelRatio、时区偏移、语言偏好这些之间必须保持逻辑自洽。随便哪个维度的取值跟目标设备画像对不上,就是暴露点。
处理阶段:模拟器特征识别的工作方式
平台爬虫要是用无头浏览器或者自动化浏览器引擎,它实际上是用一个真实的浏览器内核在跑页面脚本,比纯脚本伪装难抓得多。但模拟器本身还是会留下一些能观测到的偏差。
无头浏览器的渲染结果跟有头浏览器在字体渲染、抗锯齿、canvas像素级输出上都有可检测的差异。传感器层面更明显:真实移动设备上的加速度计、陀螺仪、光线传感器会持续产生带噪声的读数,模拟器环境里这些传感器要么压根不存在,要么返回恒定值或者理想化的正弦波。检测脚本可以通过DeviceMotionEvent和DeviceOrientationEvent的采样数据,判断噪声模式是否符合物理传感器的统计特征。恒定零值、恒定最大值、完全平滑的周期性数据,都是模拟器的典型信号。
Chromium内核在自动化模式下会暴露一些运行时特征:navigator.webdriver属性的值、CDP(Chrome DevTools Protocol)连接痕迹、自动化扩展留下的运行时变量。这些特征在不同版本的Chromium里表现不一样,但检测思路是稳的——对自动化框架做特征枚举,而不是死盯着某一个标志位。因为单个标志位容易被爬虫侧用启动参数或者运行时注入给抹掉,而多个正交特征同时出现的时候,伪装成本会非线性地往上蹿。
行为时序特征
模拟器识别还有个容易被忽略的维度:交互行为的时间序列。真实用户在页面上滚动、点击、触摸移动都有自然的加速减速过程,自动化脚本的交互要么是瞬时的,要么是匀速的。这个维度需要的采样窗口比较长,所以更适合放后端日志分析里,而不是实时跳转判定里。但对于高价值流量,在跳转之后的后续行为追踪里加入时序分析,可以给风险图谱提供回溯性的标注数据。
输出阶段:判定结果如何影响跳转决策
AB页跳转系统的输出不是简单的一句安全或者不安全。合理的输出结构应该是风险分层的。
第一层是安全流量,直接进真实落地页。第二层是可疑流量,可以进观察页或者降级页,同时打上风险标签供后续分析。第三层是明确的风险流量,进审核页或者安全页。第四层是未知流量——就是那些信号不够、既判不了真实用户也判不了爬虫的请求。
第四层流量怎么处理,是区分成熟跳转系统和粗糙跳转系统的分水岭。粗糙的做法是默认放行或者默认拦截,两种选择都有系统性代价:默认放行会放大审核暴露风险,默认拦截会持续损失真实转化。成熟的做法是对未知流量做一次低成本二次验证,比如设置一个带随机延迟的JavaScript挑战,或者让浏览器完成一个不可见的行为验证,然后根据验证结果重新分流。这个二次验证环节本身也会产生新的指纹信号,反过来又丰富了风险图谱的数据积累。
运行边界:误伤与漏放之间没有静态最优解
AB页跳转的风险图谱不是一张静态配置清单,而是一组随着对抗双方能力变化不断漂移的边界条件。任何一套固定的检测规则,跑一段时间之后都会遇到两类错误率上升的问题:真实用户被误判成爬虫(误伤),或者爬虫被放行(漏放)。
误伤的代价是直接的转化损失。一个日均三千点击的广告账户,跳转规则误伤率要是涨了三个百分点,每天就损失九十次有效访问。漏放的代价则是账户级风险。这俩之间不存在一个能一次性算出来然后永久使用的平衡点。
一个匿名化案例
有个做东南亚社交类App推广的客户,日均点击量一千二三的样子,跑Google Ads。初始配置的时候他把无头浏览器检测的阈值拉得很高,所有带自动化痕迹的流量全拦。上线第一周审核确实没出问题,但转化率比跑直链时跌了四成。排查下来发现,东南亚地区有相当比例的真实用户用的是低端Android设备,这些设备上的WebView内核本身就带着跟自动化模式相似的特征,把误判给触发了。
调整是渐进式做的:先把设备指纹验证的阈值从中位数下调到第三个四分位,让那些WebView特征的流量回到真实页;然后针对这个地区单独配了一组白名单规则,匹配特定设备型号和系统版本组合的请求直接跳过模拟器检测。调整完转化率回到直链时期的九成左右,审核风险也没有显著上升。这个案例能说明的问题是,风险图谱的边界必须根据投放地区的设备分布来校准,不能套一个全球通用的默认阈值。
爬虫伪装与模拟器识别的区别与联系
这俩概念经常被混着用,但它们描述的是同一对抗关系的两端。 爬虫伪装的主体是平台审核方,目标是让自动化请求看起来像真实用户。技术路径包括请求层伪装、浏览器指纹伪造、住宅代理IP池轮换、以及真人行为录制回放。爬虫伪装的能力上限,决定了AB页跳转系统必须检测到什么精度。
模拟器特征识别的主体是跳转系统方,目标是发现自动化浏览器留下来的环境偏差。技术路径包括渲染指纹比对、传感器噪声分析、运行时特征枚举和行为时序建模。模拟器特征识别的精度,决定了跳转系统能在多大程度上压制漏放率。 这两边的对抗是动态的。模拟器特征识别一旦公开了某类检测思路,爬虫侧下一轮迭代就会把对应特征修掉;爬虫伪装在某个维度做到以假乱真之后,这个维度在风险图谱里的权重就得往下调,检测重心挪到新维度上。AB页跳转风险图谱的价值就在于它给了这种动态调整一个结构化的框架,让维护跳转规则的人知道每个阶段该盯哪些信号、每种信号在什么条件下会失效。
使用这一框架的前提条件
AB页跳转风险图谱的构建需要三个前提。
第一,请求量必须达到能支撑统计判断的量级。日均几百个点击的账户,很多风险信号在统计上不够显著,规则调整容易被随机波动带着跑。第二,跳转系统必须能够采集和留存足够维度的请求数据,包括TLS指纹和JavaScript执行结果,不然图谱里大量节点没有数据支撑。第三,运营者得接受一个基本事实:没有一套规则能同时做到零误伤和零漏放。风险图谱的目标是让两类错误率处于可控范围内,并且在对抗升级时能够快速重新校准。
这三个前提不满足的时候,与其维护一套复杂的检测规则,不如先把跳转链路的基础稳定性做好。爬虫伪装检测是个典型的、只有在基础流量质量有保障之后才值得投入的优化环节。