滑块验证码------啥?你居然还在手动滑动,你不来试试自动滑动吗

news2024/11/25 2:37:43

测试网站

测试网站:https://www.geetest.com/demo/slide-float.html

我的giteer:秦老大大 (qin-laoda) - Gitee.com里面有我写的代码

作者备注:由于我个人原因,文章写得感觉太长,后面我会把一个知识分成多部文章,这样可以简单明了的看到了

验证码的思路有两种:一种是通过selenium来操作,这种操作简单但是运行过程速度慢,二是用js去做,这种做法比较麻烦,但是速度快

下面我来讲解一下selenium的做法 :

第一步,先在网页定位到我们要操作的地方,html的标签canvas

 思路1:要拿到两张图片,一张有缺口的图片,一张没有缺口的图片,后面我们可以通过比例来获取滑块需要滑动的距离(因为网页上的图片大小和实际的图片大小不一样,因为那是按比例缩小或者放大的)

思路2:获取缺口图片和滑块图片,来做对比得到滑块滑动的距离

如果细心的小可爱就会发现,滑块图片没有链接下载

下面我们来一一解决,首先我们要获取图片

 我们要个改一下页面的html代码如上图所示:

而实际发送回来的却是没有改的,我们需要用python代码更改一下:

代码:

  # 修改css的样式
    def get_css(self):
        time.sleep(2)
        # js语句执行 改变css
        self.driver.execute_script("document.querySelectorAll('canvas')[2].style=''")# canvas标签的个数下标从0开始,更改第三个的style

结果: 

获取图片代码如下:

    def crop_image(self,img_name):
        # 获取该图片的大小,可以通过div的框的大小进行
        img=self.driver.find_element_by_xpath('//div[@class="geetest_canvas_img geetest_absolute"]')

        # 把页面全屏化
        # self.driver.maximize_window()

        # 框的左上角的位置(x,y)
        img_left_up=img.location
        print(img_left_up)

        # 获取div框的大小(一个字典)
        print(img.size)

        # 获取图片右下角的坐标
        img_x,img_y=img_left_up["x"],img_left_up["y"]
        img_right_below_x,img_right_below_y=img_x + img.size["width"],img_y + img.size["height"]

        # 截屏(二进制)
        screen_shot=self.driver.get_screenshot_as_png()
        # 读取这个图片(读取内存中的二进制)
        by_io=BytesIO(screen_shot)
        # 打开图片
        op_img=Image.open(by_io)
        # 截取图片(截取下来的宽高),一个元组(a,b)
        cap_img=op_img.crop((int(img_x),int(img_y),int(img_right_below_x),int(img_right_below_y)))
        # 保存图片到文件中
        cap_img.save(img_name)
        return cap_img

下面我来一一讲解

我们要先清楚,因为我们没有链接下载图片,就只能截取图片,截图要清楚截图哪个地方 ,

 首先我们要截图div的框的大小

img=self.driver.find_element_by_xpath('//div[@class="geetest_canvas_img geetest_absolute"]')

我是定位了这个div框

img_left_up=img.location

这行代码比较重要,location返回一个坐标,返回哪个坐标,嘿嘿,我来告诉你们,

返回的是我们定位框的左上角的坐标(因为框和图片重合了,可以理解为图片的左上角坐标),

可是,我们要截图给光靠一个坐标还不行,我们还需得到右下角的坐标,怎么获取?我们可以获取框的大小,通过数学算法来得出

print(img.size)打印的是一个字典,返回了框的大小,

img_x,img_y=img_left_up["x"],img_left_up["y"]
img_right_below_x,img_right_below_y=img_x + img.size["width"],img_y + img.size["height"]

 这两行代码就得出了右下角的坐标了

那我们就来截取图片吧

screen_shot=self.driver.get_screenshot_as_png()

可以看出这个截图方法和我们之前的截图方法有点不一样

driver.save_screenshot("百度.png")

可以看出这个是有保存在文件里的,所以get_screenshot_as_png()是保存在内存里的(二进制)

那我们需要读取这个图片(二进制)就需要我们导入from io import BytesIO

BytesIO(二进制)

读取过后,我们还需要打开图片,

我们就需要下载模块了pip install pillow

导入模块:

from PIL import Image

打开图片

Image.open(by_io)

下面我们就要截取图片l:

cap_img=crop((x1,y1,x2,y2))

保存图片

cap_img.save("文件路径")

因为我们要保存两张图片一张原图,一张是有滑块的

原图:

滑块图:

图片的对比:

 

我们要比较无滑块的部分(利用RGB三色比较色差)

下面两张图可以让你们理解一下页面的坐标轴

 

代码如下:

 # 像素的对比
    def compare_pixel(self,img1,img2,i,j):
        pixel1=img1.load()[i,j]# 加载img1需要对比的像素并转换为RGB
        pixel2=img2.load()[i,j]# 加载img2需要对比的像素并转换为RGB
        # 对比误差范围
        threshold=60
        #RGB三颜色
        if(pixel1[0]-pixel2[0])<=threshold and (pixel1[1]-pixel2[1])<=threshold and(pixel1[2]-pixel2[2])<=threshold:
            return True
        return False

    def pixel(self,img1,img2):
        left=60#从像素60的位置开始
        has_find=False #没有发现那个凹槽
        #图片的大小(截取下来的宽高),一个元组(a,b)
        print(img1.size)
        # 一个个像素对比
        for i in range(left,img1.size[0]):#宽
            if has_find:
                break
            for j in range(img2.size[1]):
                if not self.compare_pixel(img1,img2,i,j):#img1对应的像素点(i,j)和img2对应的像素点(i,j)做对比(一个个的对比)
                    distance=i
                    print(distance)
                    has_find=True
                    # 只要碰到就立刻停止
                    break
        return distance

我先来讲解一下第二个实例方法:

left=60从像素50开始对比

has_find=False是用于判断循环的在碰见凹槽时就停止循环,

return返回遇见有凹槽第一个像素的坐标的x,(这个只是大概的后面还需要微调)

第一个实例方法:

pixel1=img1.load()[i,j]# 加载img1需要对比的像素并转换为RGB
pixel2=img2.load()[i,j]# 加载img2需要对比的像素并转换为RGB

load()加载  [i,j]对应的像素位置

threshold=60

色差

RGB有三色,三色比较,每一种色差不超过600

由于我们得到了移动的大概距离,因为有检测,我们就要躲过检测,模拟人来滑动

模拟人工滑动轨迹

代码如下:

 #移动的轨迹
    def trajectory(self,distance):
        # d=vt+1/2at**2==>位移=初速度*时间+1/2加速度*时间的平方
        # v1=v+at
        # 思路:先加速,然后加速
        # 移动轨迹
        distance-=6
        track=[]
        # 当前移动的距离
        current=0
        # 移动到某个地方开始减速
        mid=distance*3/4
        # 间隔时间(加速时间)
        t=0.1
        # 初速度
        v=0
        pass
        while current<distance:
            if(current<mid):
                a=random.randint(2,3)
            else:
                a=random.randint(4,5)
            v0=v
            v=v0+a*t
            move=v0*t+1/2*a*t**2
            current+=move
            track.append(round(move))
        return track

我们可以借用物理的位移公式

d=vt+1/2at**2==>位移=初速度*时间+1/2加速度*时间的平方

我们需要自定义初速度,加速时间,加速度

思路:如果位移小于要移动的距离,继续移动

我们还要设计一个加速度在哪个地方加大

最后我们通过位移公式来计算每加速t秒移动的距离,设计成运动轨迹

selenium操作移动

代码如下:

    def selenium(self,track):
        # js过检
        js = "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
        self.driver.execute_script(js)
        #运用行为链
        ac=ActionChains(self.driver)
        #定位
        div=self.driver.find_element_by_class_name("geetest_slider_button")
        # 按住不松
        ac.click_and_hold(div)
        # 移动
        for i in track:
            ac.move_by_offset(xoffset=i,yoffset=0)
        time.sleep(0.1)
        # 松开
        ac.release()
        # 提交行为
        ac.perform()

前面看过我写过的selenium的文章就会知道思路来,

我还是一一来解释一下:

利用行为链来操作

导入

from selenium.webdriver.common.action_chains import ActionChainsc

创建行为链对象

ac=ActionChains(self.driver)

进行操作:

定位
div=self.driver.find_element_by_class_name("geetest_slider_button")
# 按住不松
ac.click_and_hold(div)
# 移动
for i in track:
    ac.move_by_offset(xoffset=i,yoffset=0)
time.sleep(0.1)
# 松开
ac.release()

注意ac.move_by_offset(xoffset=i,yoffset=0)是每次移动多少距离,

全部代码如下:

from selenium import webdriver
import time
from PIL import Image
from io import BytesIO
import random
from selenium.webdriver.common.action_chains import ActionChains

class Radar(object):
    def __init__(self):
        self.url="https://www.geetest.com/demo/slide-float.html"
        # 创建一个浏览器
        self.driver=webdriver.Chrome()
        # 打开网页
        self.driver.get(self.url)
        # 隐式等待
        self.driver.implicitly_wait(5)

    # 定位
    def gps(self):
        return self.driver.find_element_by_xpath('//span[@class="geetest_radar_tip_content"]')

    # 点击
    def click1(self):
        self.gps().click()

    # 修改css的样式
    def get_css(self):
        # 加个休息时间,让页面加载出来
        time.sleep(2)
        # js语句执行 改变css(把有缺口的图片隐藏起来)
        self.driver.execute_script("document.querySelectorAll('canvas')[2].style=''")# canvas标签的个数下标从0开始,更改第三个的style

    # 恢复有缺口的图片
    def restore_img(self):
        # 加个休息时间,让页面加载出来
        time.sleep(2)
        # 显示出有缺口的图片
        self.driver.execute_script("document.querySelectorAll('canvas')[2].style='display:none'")

    # 截取验证码
    def crop_image(self,img_name):
        # 获取该图片的大小,可以通过div的框的大小进行
        img=self.driver.find_element_by_xpath('//div[@class="geetest_canvas_img geetest_absolute"]')

        # 把页面全屏化
        # self.driver.maximize_window()

        # 框的左上角的位置(x,y)
        img_left_up=img.location
        print(img_left_up)

        # 获取div框的大小(一个字典)
        print(img.size)

        # 获取图片右下角的坐标
        img_x,img_y=img_left_up["x"],img_left_up["y"]
        img_right_below_x,img_right_below_y=img_x + img.size["width"],img_y + img.size["height"]

        # 截屏(二进制)
        screen_shot=self.driver.get_screenshot_as_png()
        # 读取这个图片(读取内存中的二进制)
        by_io=BytesIO(screen_shot)
        # 打开图片
        op_img=Image.open(by_io)
        # 截取图片(截取下来的宽高),一个元组(a,b)
        cap_img=op_img.crop((int(img_x),int(img_y),int(img_right_below_x),int(img_right_below_y)))
        # 保存图片到文件中
        cap_img.save(img_name)
        return cap_img

    # 像素的对比
    def compare_pixel(self,img1,img2,i,j):
        pixel1=img1.load()[i,j]# 加载img1需要对比的像素并转换为RGB
        pixel2=img2.load()[i,j]# 加载img2需要对比的像素并转换为RGB
        # 对比误差范围
        threshold=60
        #RGB三颜色
        if(pixel1[0]-pixel2[0])<=threshold and (pixel1[1]-pixel2[1])<=threshold and(pixel1[2]-pixel2[2])<=threshold:
            return True
        return False

    def pixel(self,img1,img2):
        left=60#从像素60的位置开始
        has_find=False #没有发现那个凹槽
        #图片的大小(截取下来的宽高),一个元组(a,b)
        print(img1.size)
        # 一个个像素对比
        for i in range(left,img1.size[0]):#宽
            if has_find:
                break
            for j in range(img2.size[1]):
                if not self.compare_pixel(img1,img2,i,j):#img1对应的像素点(i,j)和img2对应的像素点(i,j)做对比(一个个的对比)
                    distance=i
                    print(distance)
                    has_find=True
                    # 只要碰到就立刻停止
                    break
        return distance

    #移动的轨迹
    def trajectory(self,distance):
        # d=vt+1/2at**2==>位移=初速度*时间+1/2加速度*时间的平方
        # v1=v+at
        # 思路:先加速,然后加速
        # 移动轨迹
        distance-=6
        track=[]
        # 当前移动的距离
        current=0
        # 移动到某个地方开始减速
        mid=distance*3/4
        # 间隔时间(加速时间)
        t=0.1
        # 初速度
        v=0
        pass
        while current<distance:
            if(current<mid):
                a=random.randint(2,3)
            else:
                a=random.randint(4,5)
            v0=v
            v=v0+a*t
            move=v0*t+1/2*a*t**2
            current+=move
            track.append(round(move))
        return track

    def selenium(self,track):
        # js过检
        js = "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
        self.driver.execute_script(js)
        #运用行为链
        ac=ActionChains(self.driver)
        #定位
        div=self.driver.find_element_by_class_name("geetest_slider_button")
        # 按住不松
        ac.click_and_hold(div)
        # 移动
        for i in track:
            ac.move_by_offset(xoffset=i,yoffset=0)
        time.sleep(0.1)
        # 松开
        ac.release()
        # 提交行为
        ac.perform()













def main(radar):
    radar.gps()
    radar.click1()
    #下载无缺口图片
    radar.get_css()
    img1=radar.crop_image("./截图.png")
    # 下载有缺口的图片
    radar.restore_img()
    img2=radar.crop_image("./截图1.png")
    # 获取距离
    distance=radar.pixel(img1,img2)
    # 人工模拟滑动轨迹
    track=radar.trajectory(distance)
    print(track)

    #selenium滑动
    radar.selenium(track)


if __name__ == '__main__':
    radar=Radar()
    main(radar)

总结:滑块验证码最重要的思路就是能算出移动距离,selenium移动只是一个辅助,着重看计算距离的代码,因为现在很多能检测到selenium特征的反爬,后面我会写另一种,滑块验证,有兴趣的小可爱可以过来参观

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/630358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

港科夜闻|香港科大取得重大科研突破,首度利用人工智能为阿尔兹海默症作早期风险预测...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大取得重大科研突破&#xff0c;首度利用人工智能为阿尔兹海默症作早期风险预测。香港科大校长叶玉如教授及香港科大陈雷教授带领的研究团队&#xff0c;最近开发了一套人工智能模型&#xff0c;利用遗传信息&…

WTM框架运行报错0308010C:digital envelope routines::unsupported

WTM框架运行报错0308010C:digital envelope routines::unsupported 错误描述报错原因解决方式 错误描述 我所使用WTM搭建的程序是选择的.net5.0Vue前后端分离的方式&#xff0c;项目结构选择的是“各层分离的多个项目”&#xff1b;本人并非初次使用WTM平台框架搭建项目&#…

usb 电气特性

usb 电气特性 usb 的连线 在usb 3.0 之前都有插拔方向的 只有一边有接触点 标准usb连线使用4芯电缆: 5v电源线(VBus)、差分数据线负&#xff08;D-&#xff09;差分数据线正(D&#xff09;及地线&#xff08;GND&#xff09;主要传输数据就是中间二个 D 和D- usb的数据传输…

基于 Wav2Lip-GFPGAN 深度学习模型的数字人Demo

写在前面 工作中遇到简单整理博文为 Wav2Lip-GFPGAN 环境搭建运行的 Demo理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是…

人工智能(pytorch)搭建模型10-pytorch搭建脉冲神经网络(SNN)实现及应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型10-pytorch搭建脉冲神经网络&#xff08;SNN&#xff09;实现及应用&#xff0c;脉冲神经网络&#xff08;SNN&#xff09;是一种基于生物神经系统的神经网络模型&#xff0c;它通过模拟神…

ASP.NET Core Web API入门之二:Swagger详细使用

ASP.NET Core Web API入门之二&#xff1a;Swagger详细使用 一、引言二、Swagger的作用以及优点2.1 作用2.2 优点 三、API接口添加注释3.1 编辑项目文件3.2 修改 Startup.cs 文件的 ConfigureServices 方法3.3 修改浏览器的网页标题3.4 接口添加注释 四、运行后效果 一、引言 …

(六)矢量数据的空间分析——缓冲区分析

矢量数据的空间分析——缓冲区分析 目录 矢量数据的空间分析——缓冲区分析 1.基本概念1.1图解1.2缓冲距离1.2.1固定距离1.2.2由字段决定的距离 2.缓冲区的建立2.1操作步骤2.1.1点状要素建立缓冲区2.1.2面状要素建立缓冲区 缓冲区是一组或一类地图要素&#xff08;点、线、面&a…

1.Tocmcat部署

文章目录 Tomcat部署介绍部署Tomcat安装jdk安装Tomcat添加tomcat系统服务 Tomcat部署虚拟主机tomcat多实例部署 Tomcat部署 Tomcat安装部署虚拟主机配置Tomcat优化 介绍 免费的、开放源代码的Web应用服务器Apache软件基金会(Apache Software Foundation)Jakarta项目中的- -个…

华为OD机试真题B卷 JavaScript 实现【5键键盘的输出】,附详细解题思路

一、题目描述 有一个特殊的5键键盘&#xff0c;上面有a&#xff0c;ctrl-c&#xff0c;ctrl-x&#xff0c;ctrl-v&#xff0c;ctrl-a五个键。 a键在屏幕上输出一个字母a&#xff1b;ctrl-c将当前选择的字母复制到剪贴板&#xff1b;ctrl-x将当前选择的字母复制到剪贴板&#…

【算法系列之哈希表I】leetcode15. 三数之和

242.有效的字母异位词 力扣题目链接 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 **注意&#xff1a;**若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 输入: s "anagram", t "nag…

快来给你个人微信公众号认个证吧

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 作者安全运维学习答疑交流群&#xff1a;请关注公众号回复【学习交流群】 今天我一改往日&#xff0c;不谈技术只谈谈关于个人公众号认证流程&#xff0c;突然感觉自己有点不务正业了&#xf…

go语言学习——9

文章目录 goroutine概念goroutine调度模型 channelchannel介绍定义/声明channelchannel的关闭channel遍历channel其他细节 goroutine 前言&#xff1a;统计1~90000000数字中&#xff0c;哪些是素数&#xff1f; 使用循环&#xff0c;很慢使用并发或者并行的方式&#xff0c;将任…

【数据结构】二叉树(二)

目录 一、二叉树链式结构及实现 1、二叉树的结构 2、二叉树的遍历 2.1 前序遍历 2.2 中序遍历 2.3 后序遍历 2.4 层序遍历 3、二叉树链式结构的实现 3.1 创建一个节点 3.2 二叉树节点个数 3.3 二叉树叶子节点个数 3.4 二叉树的高度 3.5 二叉树第k层节点个数 3.6 二叉树查找值…

数据库管理-第八十二期 EMCC升级教程(20230607)

数据库管理 2023-06-07 第八十二期 EMCC升级教程1 升级EMCC1.1 升级概览1.2 拷贝相关文件1.3 升级OPatch1.4 升级OMSPatcher1.5 升级WLS1.6 升级OMS 2 升级Agent2.1 升级概览2.2 拷贝相关文件2.3 安装或升级AgentPatcher2.4 升级agent 3 升级Oracle数据库ASH包总结 第八十二期 …

什么时候适合加一层?

加一层能解决问题&#xff1a; 为什么加一层能解决问题&#xff1f; 什么时候适合加一层&#xff1f; 销售说不吵的&#xff0c; 道路检测说没有超标。 业主就是睡不着。 吃瓜群众说你为啥买那边的房子。 销售说开发商骗他&#xff0c;他也是受害者。 结果没问题&#xff0…

CSS 样式语言 选择器

CSS介绍 层叠样式表&#xff0c;是一种样式表语言&#xff0c;用来描述HTML和XML文档的呈现。随着HTML的发展&#xff0c;为了满足页面设计者的要求&#xff0c;HTML添加了很多显示功能&#xff0c;但是随着这些功能的增加&#xff0c;使得HTML越来越杂乱&#xff0c;HTML 页面…

「企业安全架构」EA874:安全需求,愿景、原则和流程

安全需求愿景 在开始任何安全架构工作之前&#xff0c;定义安全需求是很重要的。这些需求应该受到业务上下文和通用需求远景文档的影响。下面是一个图表&#xff0c;它显示安全需求是企业信息安全体系结构中业务上下文的一部分。 图1 安全需求远景&#xff08;SRV&#xff09;有…

Android系统原理性问题分析 - 系统 Root 的实现原理

声明 在Android系统中经常会遇到一些系统原理性的问题&#xff0c;在此专栏中集中来讨论下。Android低版本时经常听说Root系统&#xff0c;随着Android版本的升高&#xff0c;提Root的人越来越少了。不过我在系统开发时也有客户提出为系统Root的需求&#xff0c;所以在这里分析…

【产品经理】用户增长方法论

在做用户增长为核心的产品运营推广前&#xff0c;我们应从几个方面入手——打造核心功能点、转化方式要清晰、用户反馈与转化、传播渠道要合适、建立病毒式传播规则。 2017年&#xff0c;以营销见长的可口可乐公司将设置了24年之久的首席营销官&#xff08;CMO&#xff09;撤销…

[Maven高级]->近万字文章带你深入了解Maven

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;JavaEE ⭐如果觉得文章写的不错&#xff0c;欢迎点个关注一键三连&#x1f609;有写的不好的地方也欢迎指正&…