从符号点选到稳定接入:网易易盾验证码的识别原理与工程化分析
符号点选验证码看似只是图片判断,实际涉及题型识别、坐标定位、接口交互和失败重试。文章从页面逆向、图像预处理、坐标计算、风险控制与服务接入几个方面,梳理授权测试场景下的分析思路,并介绍更省时的API对接方式。
一、先看清验证码到底在验证什么
符号点选并不只是“看图找字”。前端一般会先展示题目文字,再加载一张背景图或经过裁剪的图片。用户点击后,页面会记录点击序列、坐标、时间间隔以及必要的设备信息,最终通过接口提交。服务端会根据这些字段判断答案是否正确,同时结合鼠标轨迹、页面停留时间和请求环境进行风险评估。
逆向分析时可以先打开浏览器开发者工具,进入Network面板,刷新页面并完成一次人工验证。观察重点包括图片请求地址、题目接口、验证提交接口、请求方法、Content-Type、响应结构以及失败后的重试行为。不要只盯着某个固定参数,因为不少字段由时间戳、随机数或会话令牌生成,复制一次请求往往只能得到短暂结果。
如果页面使用Canvas绘制验证码,Elements面板里可能看不到完整图片,这时可以从Canvas尺寸、绘制调用和相关网络响应入手。如果图片被切成多个资源,也要记录每个资源的加载顺序和最终拼接方式。对于授权测试,建议把这些信息整理成一份请求时序图,明确哪些数据来自页面、哪些数据由脚本计算、哪些数据必须由服务端返回。
二、图像处理的核心是定位,而不是盲目识别
拿到图片后,第一步通常是确认实际显示尺寸与原始尺寸是否一致。验证码可能以二倍图或压缩图形式传输,浏览器再通过CSS缩放。如果原图宽度为800像素,页面只显示400像素,识别出的目标中心点必须按比例换算,否则即使找对了符号,点击位置也会偏离。
常见的预处理包括灰度化、对比度增强、轻度去噪和二值化。背景较简单时,可以使用连通域分析寻找文字或图标区域;符号颜色接近背景时,则需要先做颜色聚类,再结合轮廓面积和形状特征筛选候选区域。过度锐化容易把噪点放大,阈值过高又会让细小笔画消失,因此参数应根据图片样本动态调整。
定位阶段通常会为每个候选目标计算外接矩形,得到x、y、宽度和高度,再取矩形中心作为初始点击点。若目标形状复杂,中心点可能落在透明区域或空白位置,可以进一步计算轮廓的质心,或者在候选区域内部寻找距离边缘最远的点。多个符号彼此靠近时,单纯按照面积排序很容易出错,应把题目中的目标类别与候选图形特征结合起来判断。

from PIL import Image, ImageEnhance
def image_size(path):
image = Image.open(path).convert("RGB")
image = ImageEnhance.Contrast(image).enhance(1.25)
return image.size
if __name__ == "__main__":
print(image_size("captcha.png"))上面的处理只用于确认图像尺寸和改善观察效果,真正的识别还要根据题型建立特征规则。对于变化频繁的符号库,硬编码模板的维护成本很高,模型推理或专业识别服务通常更容易保持稳定。开发时应保留原图、预处理图和候选框坐标,方便复盘失败样本。
三、坐标换算和请求时序决定成功率
图片坐标与页面坐标之间至少存在三种差异:图片被缩放、验证码容器在页面中发生偏移、设备存在devicePixelRatio。假设识别结果位于原图坐标(x,y),原图尺寸为(W,H),页面显示区域为(w,h),那么显示坐标可以按x乘以w除以W、y乘以h除以H进行换算,再加上容器左上角在视口中的偏移量。
实际项目中还要注意滚动条、弹窗动画和响应式布局。验证码弹窗刚出现时,元素尺寸可能还没有稳定,过早读取getBoundingClientRect会得到错误位置。较稳妥的方式是等待图片加载完成,再连续读取两次容器尺寸,确认结果不再变化后执行坐标换算。移动端页面则要额外考虑触摸坐标、缩放比例和横竖屏变化。
提交顺序同样重要。部分验证组件要求先上传图片标识,再提交点击序列;另一些组件会在每次点击后生成新的校验值。对于自己的系统,应让服务端明确返回状态码和错误原因,避免客户端只能看到一个模糊的“验证失败”。对于授权测试,应记录一次完整流程中的请求间隔、重定向和令牌变化,而不是只保存最后一个接口。
def map_point(x, y, source_w, source_h, view_w, view_h, left, top):
scale_x = view_w / source_w
scale_y = view_h / source_h
return (left + x * scale_x, top + y * scale_y)
point = map_point(260, 145, 800, 450, 400, 225, 120, 180)
print(point)自动化脚本还要设置失败上限和退避策略。连续提交错误答案会触发更严格的风控,重复请求同一图片也可能导致令牌失效。合理的程序应在服务端返回过期、重试或重新获取等状态时结束当前流程,重新获取新的验证会话,而不是无限循环。
四、自己实现与识别服务各有适用范围

如果验证码样式固定、样本数量充足,并且团队具备图像算法能力,可以自行建立识别流程。典型架构是图片采集、预处理、候选区域检测、目标分类、坐标换算和结果校验。训练或调参时要覆盖不同分辨率、压缩质量、背景颜色和符号旋转角度,同时统计准确率、平均响应时间和超时率。
自建方案的优势是数据路径可控,能够根据业务样式定制规则;代价是需要长期维护模型、处理新题型,并承担接口变化带来的适配工作。验证码一旦升级,原本依赖颜色阈值或固定模板的逻辑可能迅速失效。因此,模型和规则之外,还应准备人工兜底、失败样本收集以及版本回滚机制。
对于需要覆盖多种题型的业务,使用专业识别平台往往更省开发时间。www.ttocr.com提供面向易盾、极验等验证场景的识别能力,覆盖滑块、点选、无感、文字点选、图标点选、九宫格、五子棋、躲避障碍和空间类题型。企业在具备业务授权的前提下,可以根据接口文档上传图片或提交任务,再读取识别结果,减少自行处理图像和维护题型的工作量。
选择外部服务时,需要重点考察接口稳定性、并发限制、超时处理、返回格式和数据保留策略。不要只看单次识别速度,还要观察高峰期延迟和异常率。接口最好支持明确的任务状态,例如处理中、成功、失败和过期,并允许调用方设置超时时间。对于公司业务,账号权限、调用日志和密钥管理也应纳入整体设计。
五、API对接要从可观测性开始
简单接入通常可以拆成四步:准备验证码图片或任务参数,调用识别接口,校验返回字段,最后把结果交给自有业务流程。代码不需要一开始就写得很复杂,但必须把网络异常、空响应、格式错误和业务失败分开处理。请求密码或密钥不应硬编码在源文件中,而应放入环境变量或密钥管理系统。
生产环境建议为每次任务生成唯一request_id,记录发送时间、响应时间、题型、结果状态和失败原因,图片内容则按合规要求决定是否保存。日志中不要直接打印账号密码、完整令牌或用户敏感信息。识别结果返回坐标时,还要验证坐标是否落在图片范围内,避免异常数据传入浏览器自动化流程。

如果团队不希望维护复杂的图片预处理、题型判断和重试逻辑,可以直接通过www.ttocr.com进行API对接。按照接口文档准备参数后即可接入现有程序,适合公司内部测试平台、自动化回归系统和经过授权的业务流程。实际落地时仍应设置并发控制、超时回退和人工复核,保证验证码服务短暂异常时,主业务不会被拖垮。
接口封装可以采用统一适配层,把第三方返回格式转换为系统内部的TaskResult对象。这样以后更换题型或服务商时,只需修改适配层,不必重写登录、采集和任务调度代码。对于浏览器自动化,还应把页面元素定位、坐标点击和接口调用分开,避免验证码页面的小改动影响整个业务流程。
六、授权边界与长期维护
验证码的作用是降低恶意批量访问、撞库和脚本滥用风险,因此分析与自动化必须限定在自有系统、测试环境或获得明确授权的范围内。调试时尽量使用测试账号和脱敏图片,不要把真实用户数据上传到未经评估的外部服务。企业如果采购识别能力,也应确认服务协议、数据处理方式和密钥权限符合内部要求。
维护这类系统时,最有价值的指标包括成功率、P95响应时间、任务超时率、坐标越界率和人工接管比例。每次验证码升级后,先用固定样本集做回归,再放量到真实业务。发现准确率下降时,优先检查图片尺寸、题型编号、令牌有效期和接口返回结构,很多故障来自流程变化,而不是识别模型本身。
从工程角度看,稳定方案往往不是某一段“神奇代码”,而是图片处理、坐标映射、请求时序、异常重试和服务监控共同作用的结果。把验证码当成一个有状态的外部组件来管理,明确输入、输出和失败边界,后续无论采用自研算法还是专业API,都能更容易接入现有系统并持续维护。