美文网首页
爬虫滑动验证识别 opencv-python

爬虫滑动验证识别 opencv-python

作者: 木语沉心 | 来源:发表于2020-03-16 15:25 被阅读0次

    前言

    滑块验证码破解是一直都是一个棘手的问题,毕竟多数网站都会采用滑块验证码要搞现在的滑块验证码绕不开图像处理,图像处理当然是首推OpenCV-Python(开箱即用) 我的速成OpenCV非常菜, 发现问题就直接指出嘛,不用走流程啦!

    环境
    pip install opencv-python

    OpenCV的使用
    相关的API我也是边用边查的,用得也是相当生疏!具体的常用方法大家只好自行百度

    实现原理及方法

    腾讯滑块验证
    这次搞得目标就是腾讯滑块验证码,调用腾讯滑块这个接口的网站还是挺多的,比如非常好用的在线画图网站ProcessOn,其中滑块验证部分类似这样子的:

    image.png

    破解滑块验证码最为关键的地方在于找到滑块缺口的位置,找到缺口位置后就可以利用Selenium模拟拖动滑块到指定位置实现破解,之前的老办法就是将完整图的像素点和带缺口图的像素点进行比较从而得到缺口位置,但是现在一般不会将完整图暴露给我们,所以只有在带有缺口的图上进行处理。我这里一共有两种方案进行缺口位置识别,一种是基于模板匹配的,另一种是基于轮廓检测的,下面会细讲两种方案的实现方法。

    模板匹配识别缺口
    具体是实现过程如下:
    1.处理滑块的图片

    • 灰度化滑块图片
    • 处理一下滑块图中滑块的外圈
    • 使用inRange二值化滑块图
    • 使用开运算去除白色噪点

    运行结果如下所示(左侧为原始滑块,右侧为处理后的滑块):


    image.png

    2.处理带缺口的图片

    • 先来个高斯滤波去噪
    • 灰度化带缺口图
    • 使用阈值二值化该图

    运行结果如下所示(左侧为原始图,右侧为处理后的图):


    image.png

    3.进行模板匹配
    调用模板匹配API并圈出匹配上的区域,结果如下所示:

    image.png

    警告警告警告
    这种方法的缺口识别率在50%左右,很大一部分原因是滑块图的背景为纯白色,这在匹配时会产生很大的干扰,要是能将滑块图的背景变为透明,正确的匹配率可以达到90%以上

    如果大家有任何将滑块图的背景变为透明的办法,可以留言到评论区,我真的万分感谢!!!下面是现阶段的实现代码:

    # encoding:utf-8
    import cv2 as cv
    import numpy as np
    
    # 对滑块进行二值化处理
    def handle_img1(image):
        kernel = np.ones((8, 8), np.uint8)  # 去滑块的前景噪声内核
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        width, heigth = gray.shape
        for h in range(heigth):
            for w in range(width):
                if gray[w, h] == 0:
                    gray[w, h] = 96
        # cv.imshow('gray', gray)
        binary = cv.inRange(gray, 96, 96)
        res = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)  # 开运算去除白色噪点
        # cv.imshow('res', res)
        return res
    
    # 模板匹配(用于寻找缺口有点误差)
    def template_match(img_target, img_template):
        tpl = handle_img1(img_template)  # 误差来源就在于滑块的背景图为白色
        blurred = cv.GaussianBlur(img_target, (3, 3), 0)  # 目标图高斯滤波
        gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
        ret, target = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)  # 目标图二值化
        # cv.imshow("template", tpl)
        # cv.imshow("target", target)
        method = cv.TM_CCOEFF_NORMED
        width, height = tpl.shape[:2]
        result = cv.matchTemplate(target, tpl, method)
        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
        left_up = max_loc
        right_down = (left_up[0] + height, left_up[1] + width)
        cv.rectangle(img_target, left_up, right_down, (0, 0, 255), 2)
        cv.imshow('res', img_target)
    
    if __name__ == '__main__':
        img0 = cv.imread('./demo/3/hycdn_3.jpg')
        img1 = cv.imread('./demo/3/hycdn_3_2.png')
        template_match(img0, img1)
        cv.waitKey(0)
        cv.destroyAllWindows()
    
    

    轮廓检测识别缺口
    基于轮廓检测缺口的思路简单很多,加上合理的条件识别率在95%以上,实现过程如下:

    • 带缺口图高斯模糊去噪
    • (200,400)的阈值做Canny边缘检测
    • 寻找轮廓
    • 对已有的轮廓做约束,比如轮廓的面积范围,轮廓的周长范围
      匹配结果如下:


      image.png

      实现代码如下:

    # encoding:utf-8
    import cv2 as cv
    
    def get_pos(image):
        blurred = cv.GaussianBlur(image, (5, 5), 0)
        canny = cv.Canny(blurred, 200, 400)
        contours, hierarchy = cv.findContours(canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        for i, contour in enumerate(contours):
            M = cv.moments(contour)
            if M['m00'] == 0:
                cx = cy = 0
            else:
                cx, cy = M['m10'] / M['m00'], M['m01'] / M['m00']
            if 6000 < cv.contourArea(contour) < 8000 and 370 < cv.arcLength(contour, True) < 390:
                if cx < 400:
                    continue
                x, y, w, h = cv.boundingRect(contour)  # 外接矩形
                cv.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
                cv.imshow('image', image)
                return x
        return 0
    
    if __name__ == '__main__':
        img0 = cv.imread('./demo/4/hycdn_4.jpg')
        get_pos(img0)
        cv.waitKey(0)
        cv.destroyAllWindows()
    

    遗留问题

    问题1
    如何将滑块图的纯白背景变为透明背景?
    进一步降噪的处理方法

    问题2
    使用Selenium和轨迹算法拖动滑块时将滑块拖出左侧的范围之外,轨迹算法是先加速后减速整体是向前移动的,按道理来说不可能往回走,但是模拟拖动的时候会出现滑块向后拖动且拖出范围的现象,这问题如何解决?
    问题3

    终极问题:
    selenium 在某些网站上根本获取不到弹出的验证模块标签, 查看driver_source确实没有返回滑动按钮部分的源码, 拿不到按钮就不能进行模拟操作 暂时无解!!!
    参考链接:https://github.com/Forbilly/captcha_cracking

    更新新方法

    参考: github_addr

    相关文章

      网友评论

          本文标题:爬虫滑动验证识别 opencv-python

          本文链接:https://www.haomeiwen.com/subject/cswgehtx.html