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

上一节我们分析了滑动验证码的破解的原理以及大概的实现方式。这一节我们将讨论下具体的技术实现细节。
工欲善其事必先利其器,我们需要借助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,写出驱动脚本,直接让他去滑动,我们的问题最终也就解决了。

总结

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

滑动验证码的破解(一)、原理介绍

最近有小伙伴和我讨论了验证码破解识别的话题,希望我帮忙实现一个滑动验证码破解识别的原型。今天我们就来聊聊这个话题。
验证码的破解是一个很有趣的话题,破解的而方式也有很多。譬如最机械的使用人工点击,亦或是相关的视觉处理算法,甚至是近年来很火热的机器学习等等。近年来,随着识别的技术提高,相应的验证码制造识别的难度也在提高,表现出越来越智能化。
下面我们直接进入主题,谈一谈今天的主角滑动验证码的破解。首先,我们来看一下,滑动验证码长啥样,我随便上网找了个图片。


再来看一张

我们可以看到大概是这样的,页面上有一张图片,图片右侧有两个随机的几何图形的阴影图片,图片左侧有一个目标几何图形。图片下方是一个滑块。
具体验证逻辑是这样的

    拖动下方滑块;
    上方的几何图形会跟着滑块移动;
    移动上方的几何图形,直到几何图形达到右侧相似阴影;
    识别完成。

有的小伙伴可能觉得我讲这个很啰嗦,这么简单的逻辑谁不知道。我为什么要介绍这个呢?后文的破解识别和这个有很大的关系,俗话说知己知彼,百战不殆。
言归正传,我们究竟应该如何做呢?我们想要破解识别出结果,必须要解决两个问题

    1.找出图中相同几何阴影图片的位置。
    2.计算出目标几何图片滑块和相同几何阴影图片的位置距离。

我们带着问题去寻找答案,似乎就不在那么困难了。
通过上面的分析,我们会发现一些有趣现象。

    1.图中几何阴影的识别不就转换成了图片识别问题了吗?
    2.位置识别我也许不是很好计算,我们可以换一个思路,上面的分析我们知道目标滑块和拖动滑块是同进退的,我们只要在上一步的基础上计算下方出滑块和相同几何阴影图片的位置距离,问题不就迎刃而解了吗?

有了上面的数据,我们就可以通过计算出图片在整个屏幕的相对位置,计算出最终的滑动距离。接下来问题就好办多了,八仙过海,各显神通。
我的小伙伴告诉我,它使用的是Selenium来实现的。记得我以前使用过Appium来实现过APP端的自动化的测试,他和Selenium的原理一样。我们只要写几行代码驱动Appium,那么从PC到移动端,所有的场景都能完美解决,理论上讲所有的技术障碍我们都已经扫清了。
当然这里也有一些问题,比如说Selenium如何模拟人类的滑动操作,模仿出一个变速抖动运动轨迹等等问题,这些本文不做讨论。我们只关心滑动验证码本身问题。回过头来,我们继续聚焦初始问题,实现图片的识别和距离计算。到底需要怎么做呢?下一节,我们将通过撸代码的方式为大家做具体的剖析。