上期给大家分享过拼多多的双阴影滑块验证码的解决方案,后来对指令进行改良后上线了更具通用性的指令“滑块拼图验证码免费版”。

该指令可以通杀大部分滑块拼图验证码,如:常规的、缺块有内发光的、背景有多缺口的、缺块元素捕获不了的。


但是在使用过程中有点摸不着头脑,特别是滑块拼图验证码这个指令,居然要选3个元素,哪个是缺块元素,哪个是拖拽元素,傻傻分不清楚。今天就给大家写一下这个指令的用法和原理。
PS:虽然是免费版但是准确率也很高哦!可以取代付费的“验证码识别”指令,给大家省钱!
目前指令已经支持web和win的元素,可覆盖大部分的使用场景。使用方式基本一致,需要选定对应的网页对象或窗口对象,捕获背景元素、缺块元素、拖拽滑块元素。
使用说明:


如图:
背景元素是最大的方框(验证码的背景)
缺块元素是背景框内的小方框(待移动的拼图缺块)
拖拽滑块元素就是最下方的滑块
指令还额外提供了两个参数:
偏移距离:当每次识别结果总是与正确位置偏移,且偏移的距离相对稳定,则可以在这里填入一个偏移值,来抵消偏移量。
重试次数:验证失败后自动重试的次数(部分网址验证成功仍会触发重试,可将重试次数设置为0次,若需重试可自行搭建循环逻辑实现。触发原因可能是验证成功后背景元素和缺块元素会停留一段时间才消失,导致指令误判为验证失败。)
使用的小技巧:
——如果验证码中的缺块元素无法捕获,还能使用这个指令吗?
——或许可以!
在大部分场景中,可以使用“拖拽滑块”元素代替“缺块元素”,运行发现可以正确通过验证。至于原因,在接下来的内容中会向大家解释清楚。
滑块拼图验证码指令的实现原理:
该指令实际上是使用了OpenCV这个python库,进行图像的处理识别,最终返回一个最佳匹配的位置(缺口与缺块的x轴距离),再通过移动拖拽滑块来完成验证。
具体步骤:
1、把验证码图片完整截图下来

2、通过获取缺块元素的位置信息,把缺块元素与背景元素一分为二

----------------------------------------------code----------------------------------------------
# 读取背景图片和缺口图片
bg_img = cv2.imread('bg.jpg') # 背景图片
tp_img = cv2.imread('tp.png') # 缺口图片
----------------------------------------------code----------------------------------------------
3、识别图片边缘(使用cv2.Canny()函数完成)
----------------------------------------------code----------------------------------------------
# 识别图片边缘
bg_edge = cv2.Canny(bg_img, 100, 200)
tp_edge = cv2.Canny(tp_img, 100, 200)
----------------------------------------------code----------------------------------------------
4、将识别边缘得到的灰度图,转为RGB格式

----------------------------------------------code----------------------------------------------
# 转换图片格式
bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
----------------------------------------------code----------------------------------------------
5、缺口匹配(使用cv2.matchTemplate()函数)
----------------------------------------------code----------------------------------------------
# 缺口匹配
res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
----------------------------------------------code----------------------------------------------
res为每个位置的匹配结果,代表了匹配的概率,选出其中「概率最高」的点,即为缺口匹配的位置:
----------------------------------------------code----------------------------------------------
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 寻找最优匹配
----------------------------------------------code----------------------------------------------
min_val,max_val,min_loc,max_loc分别为匹配的最小值、匹配的最大值、最小值的位置、最大值的位置。
缺口的位置,其X轴坐标为:
----------------------------------------------code----------------------------------------------
X = max_loc[0]
----------------------------------------------code----------------------------------------------
在X坐标位置打上红色标记,可以看到标记刚好位于缺口位置,说明识别正确了。

以上就是该指令的实现原理啦~
最后再解释一下上面留的一个小问题:
为什么在大部分场景中,可以使用“拖拽滑块”元素代替“缺块元素”,也可以正确通过验证?
正常来说,通过读取“缺块元素”左右边界的位置,就能把完整的验证码图片切分成缺块部分和缺口部分,但是当缺块元素无法捕获时,我们只能用“拖拽滑块”的边界来切分图片。


左侧是用“缺块元素”,右侧是用“拖拽滑块”,可以看到也是能切分出大部分的缺块,拿来与缺口进行匹配,基本都能匹配得到的。