滑动验证码的破解(二)、具体实现

上一节我们分析了滑动验证码的破解的原理以及大概的实现方式。这一节我们将讨论下具体的技术实现细节。
工欲善其事必先利其器,我们需要借助openCV视觉处理库来处理识别,因为简单好用,本身这个图片识别也不复杂,都是固定的几何图形。

        # 载入滑块匹配图片
        src = cv2.imread(path.format('crop-',i,'.jpg'))
        # 载入背景图片
        back = cv2.imread(path.format(i,'','.png'))
        # 裁剪,这里的1/3参数可以根据实际情况调整,获取这一块图片
        start = int((back.shape[1])*10/30)
        crop = back[y:back.shape[0]-y,start:back.shape[1]]
        # 锐化滤波
        kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
        src = cv2.filter2D(src,-1,kernel=kernel)

        # 灰度化
        src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
        crop = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)

        # 获取长度宽度
        h, w = src.shape[:2]
        # 匹配模板,函数自带
        ss = cv2.matchTemplate(crop,src,cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(ss)
        # 通过左上右下定位出图形位置
        # 左上角
        left_top = max_loc
        # 右下角
        right_bottom = (left_top[0] + w, left_top[1]+h)
        # 画出矩形位置
        re = cv2.rectangle(crop, left_top, right_bottom, 255, 2)
        # 拼接查看图片
        cv2.imwrite(path.format('crop-',i,'-des.png'), re, [int(cv2.IMWRITE_JPEG_QUALITY)])

核心的逻辑还是很简单的:

    1.分别载入识别图形和背景阴影图片;
    2.我们分析图片可以看出,具体的阴影位置只能存在于和目标滑块在一条线上;
    3.获取这一块图片,以加快识别,减少不必要的浪费;
    4.对图像锐化滤波,
    5.对图片灰化处理,方便识别
    6.匹配模板,找出阴影位置
    7.通过上一步获取的结果,再返回到原图中裁剪,匹配出最终位置

总的来说,使用自带的匹配模板还是很简答的,避免了我们徒手实现。但是我们也不是盲目使用,我们需要在真正处理前对图片进行一些处理。通过观察分析,我们可以看到,因为这种滑动验证码只能进行水平滑动,那就意味着最终的识别区域必将存在于和左侧滑块处于同一条水平线线上的区域。那么我们离目标又近了一步,我们只需要处理其中一部分图片就可以了。我们需要对图片进行裁剪,即可获取这一块图片。
当然图片还可以进行其他的算法处理用以获得更精确结果,小伙伴可以自行尝试。
我们来看一下识别的结果:


识别率还是可以的,我们粗略地统计了一下,识别成功率大概在90%左右。感兴趣的小伙伴可以优化一下图片处理逻辑,使用更好的处理算法以提高成功率。
再回到上一节,我们获得了图片的具体数据,只要在加上验证码在屏幕中的相对位置,我们就可以计算出绝对数据。最后把这些参数传递给selenium,写出驱动脚本,直接让他去滑动,我们的问题最终也就解决了。

总结

总的来说,滑动验证码识别实现起来,不是很困难。关键在于怎么分析出问题,以及找到处理问题的方法、步骤,然后按顺序去处理。
所谓道高一尺,魔高一丈。今天你破解了一种验证码,明天又会出现新形式的验证码。两者此消彼长,没有孰强孰弱。而两者真正的平衡点,在于正常用户能够理解并能完成验证罢了。
本文只做技术上的交流探讨,所有素材选取均出自互联网,不针对任何第三方。如由此引发的其他相关法律、法规问题,与本网站无关。

发表评论

邮箱地址不会被公开。 必填项已用*标注