滑动验证码 转载:https://mp.weixin.qq.com/s/4cvr3mqKD0jkZNVDky4y7w

今天的主角是滑动验证码,现在有很多网站使用了极验验证码来智能反爬虫,其中有一种是滑动验证码,具体来说就是拖动滑块来拼合图像,若图像完全拼合,则验证成功。下图是B站的登录验证码,便是采用了极验的滑动验证码,一起来看看如何破解吧!

 

 

先打开B站的登录页面,https://passport.bilibili.com/login,输入账号密码之后点击登录便会弹出上述的滑动验证码。

 

将任务拆分有助于我们解决问题,解决这个滑动验证码我们可以分为这么两个步骤:

1)识别图片缺口

2)模拟拖动滑块

那么就一步一步来吧~

 

图片缺口识别

 

可以看到的是缺口图的颜色与周围有显著不同,我们只需要拿到不含缺口的原图进行对比就能够找到这个缺口的坐标。

 

打开开发者工具,看源代码上是否包含两张图片的url链接,这样我们可以直接下载下来分析对比。不巧的是,我们没有发现它的踪迹。

 

 

但当我们将上图源代码中的类别为"geetest_canvas_fullbg geetest_fade geetest_absolute"的style设置为空,即可显示没有缺口的原图。 

 

 

知道如何获得这两张图片之后,我们可以通过get_geetest_image函数来获取滑动验证码的图片,具体是用了 Selenium 工具选取图片元素,然后得到其所在位置以及大小,随后获取整个网页的截图,再将这个滑动验证码从截图中裁切出来。

 

    def get_geetest_image(self,name,flag):

        """
        获得验证码图片        
        """
        bottom,top,left,right=self.get_position(flag)
        print("验证图片位置",bottom,top,left,right)
        screenshot=self.get_screenshot()
        captcha=screenshot.crop((left,bottom,right,top))
        captcha.save(name)
        return captcha

    def get_position(self, flag):

        """
        获取验证码图片位置
        """
        img=self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "canvas.geetest_canvas_slice")))
        time.sleep(2)                
        if flag:
            # 执行js获取不带缺口的原图
            self.browser.execute_script('document.getElementsByClassName("geetest_canvas_fullbg")[0].setAttribute("style", "")')
        else:
            # 执行js,把缺口复原
            self.browser.execute_script('document.getElementsByClassName("geetest_canvas_fullbg")[0].setAttribute("style", "opacity: 1; display: none;")')
        location=img.location
        print("图片坐标为:{}".format(location))
        size=img.size
        print("图片大小为:{}".format(size))
        bottom,top,left,right=location["y"],location["y"]+size["height"],location["x"],location["x"]+size["width"]

        return (bottom,top,left,right)

 

我们通过selenium执行js代码,获取不带缺口的原图和我们最先见到的有缺口的图。

 

图片获取之后,来对比图片各个像素通道的差异来获取缺口的位置就行。我们宽泛的认为,像素相差在一定范围内视为相同,像素相差大于阈值视为发现缺口,便由此得到了缺口的坐标信息。

 

      def get_gap(self, image1, image2):

        """
        获取缺口位置,通过比较像素值
        """
        for i in range(LEFT, image1.size[0]):
            for j in range(image1.size[1]):
                if not self.is_pixel_equal(image1,image2,i,j):
                    return i
        return LEFT

    def is_pixel_equal(self,image1,image2,x,y):

        """
        像素值比较,若三个通道均为出现超过阈值的变化,返回True
        """
        pixel1=image1.load()[x, y]
        pixel2=image2.load()[x, y]
        if abs(pixel1[0]-pixel2[0])<THRESHOLD and abs(pixel1[1]-pixel2[1])<THRESHOLD and abs(pixel1[2]-pixel2[2])<THRESHOLD:
            return True
        else:
            return False
  

 

加上LEFT这个偏移量,是因为带缺口的图还附带了滑块,我们需要将滑块的长度范围舍弃,即在滑块的右侧开始像素的比较,这样我们就可以得到缺口的位置了。

 

 

模拟拖动滑块

 

要拖动滑块我们需要先得到滑块通过简单的selenium操作即可。

    def get_slider(self):

        """
        获取滑块
        """
        return self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "geetest_slider_button")))

 

这里需要用到简单的高中物理知识,为了让selenium模拟人的操作,我们需要将滑块先加速运动,再减速运动,这样会比较符合人的操作。我们采用匀加速和匀减速的方法,方便套用物理公式。模拟前4/5路程为匀加速路程,后1/5路程是匀减速路程,t是计算的时间间隔。

 

    def get_track(self,distance):

        """
        获取滑块移动轨迹的列表,distance是缺口的左侧横坐标值
        """
        track=[]
        current=0
        mid=distance*0.8
        t=0.2
        v=0
        while current<distance:
            if current<mid:
                a=2.5
            else:
                a=-3.5
            v0=v
            v=v0+a*t
            move=v0*t+ 0.5*a*t*t
            current+=move
            track.append(round(move))
        return track

 

然后,我们只需要按照计算得到的运动轨迹操控小滑块运动即可。下面是破解过程展示。

 

 

posted on   我和你并没有不同  阅读(825)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2018-10-22 七周七并发模型
2017-10-22 开工:创建虚拟机,xshell连接虚拟机,复制虚拟机,docker安装,添加加速器
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示