前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >基于selenium自动化的滑动验证码破解

基于selenium自动化的滑动验证码破解

作者头像
andrew_a
发布于 2019-07-30 06:47:47
发布于 2019-07-30 06:47:47
1.7K00
代码可运行
举报
运行总次数:0
代码可运行

常见的滑动验证码就是哔哩哔哩了,就以哔哩哔哩作为例子

1、拿到完整图片

2、拿到有缺口的图片

3、计算滑动距离

4、滑动(如何避免被识别出来)

当鼠标放在上面不点击的时候,就会产生完整的图

当点击的时候就会出现有缺口的图片

在图片上右击检查,就会到图片的位置

然后打开图片的URL,你会发现这是一个乱序的图片

如何解决这个问题,

第一种解决办法:

就是将获取到的图片的按照前端的顺序,重新拼接

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_merge_image(self, filename, location_list):
    """
    合并图像,并还原图像
    :return:
    """
    im = image.open(filename)
    new_im = image.new('RGB', (260, 116))  # width 260px, height 116px
    im_list_upper = []
    im_list_down = []  # 以列表形式储存按照一定的顺序储存图片碎片
    for location in location_list:  # 截取对应位置的图,并添加到列表中
        if location['y'] == -58:
            im_list_upper.append(im.crop((abs(location['x']), 58, abs(location['x'])+10, 166)))
        if location['y'] == 0:
            im_list_down.append(im.crop((abs(location['x']), 0, abs(location['x']) + 10, 58)))

    x_offset = 0
    for im in im_list_upper:
        new_im.paste(im, (x_offset, 0))
        x_offset += im.size[0]
    x_offset = 0
    for im in im_list_down:
        new_im.paste(im, (x_offset, 58))
        x_offset += im.size[0]
    new_im.save(filename)
    time.sleep(1)
    # 将图片碎片组合到复制到新图片上 
    return new_im

第二种:

截图,分别截图,完整的时候截一次图(截图全屏),不用管是否乱序,获取图片的坐标,将截图再次按照坐标截图处理,这样就能获得完整的图和有缺口的图。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_image(driver):
    img = driver.find_element_by_class_name('gt_cut_fullbg')
    time.sleep(2)
    location = img.location
    size = img.size
    left = location['x']
    top = location['y']
    right = left + size['width']
    bottom = top + size['height']

    page_snap_obj = get_snap(driver)
    image_obj = page_snap_obj.crop((left, top, right, bottom))
    # image_obj.show()
    return image_obj
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_snap(driver):
    driver.save_screenshot('full_snap.png')
    page_snap_obj = Image.open('full_snap.png')
    return page_snap_obj

使用PIL裁切图片

使用PIL需要引用Image,使用Image的open(file)方法可以返回打开的图片,使用crop((x0,y0,x1,y1))方法可以对图片做裁切。

区域由一个4元组定义,表示为坐标是 (left, upper, right, lower),Python Imaging Library 使用左上角为 (0, 0)的坐标系统

box(100,100,200,200)就表示在原始图像中以左上角为坐标原点,截取一个100*100(像素为单位)的图像,为方便理解,如下为示意图box(b1,a1,b2,a2)

这样我们就拿到了图片一个是完整的,一个是有缺口的。

第三步就是计算要滑动的距离了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def is_pixel_equal(self, img1, img2, x, y):
    """
    判断两个像素是否相同
    :param img1:
    :param img2:
    :param x: 位置x
    :param y: 位置y
    :return:
    """
    # 取两张图片的像素点
    pix1 = img1.load()[x, y]
    pix2 = img2.load()[x, y]
    threshold = 60
    if (abs(pix1[0] - pix2[0] < threshold) and abs(pix1[1] - pix2[1] < threshold) and abs(
        pix1[2] - pix2[2] < threshold)):
        return True
    else:
        return False
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_pag(self, img1, img2):
    """
    获取偏移量
    :param img1:不带缺口
    :param img2:带缺口
    :return:
    """
    left = 43
    for i in range(left, img1.size[0]):
        for j in range(img1.size[1]):
            if not self.is_pixel_equal(img1, img2, i, j):
                left = i
                return left
    return left

得到了滑动的距离就是计算如何去滑动了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_track(self, distance):
    """
    根据偏移量获取移动轨迹
    :param distance:
    :return:
    """
    distance += 24
    # 移动轨迹
    track = []
    # 当前位移
    current = 0
    # 减速阀值
    mid = distance * 3 / 5
    # 计算阀值
    t = 0.2
    # 计算初速度
    v = 0
    while current < distance:
        if current < mid:
            # 加速度
            a = 2
        else:
            # 加速度为-3
            a = -3
        # 初速度为
        v0 = v
        # 移动距离x = v0t+1/2*a^2
        move = v0*t + 1/2*a*t*t
        # 当前位移
        current += move
        # 加入轨迹
        track.append(round(move))
        # 速度已到达v,该速度作为下次的初速度
        v = v0 + a*t
    # track = [-3, -3, -2, -2, -2, -2, -2, -1, -1, -1]
    return track
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def get_track(self, x_offset):

        track = list()
        length = x_offset - 6
        x = random.randint(1,5)
        while length - x >4:
            track.append([x,0,0])
            length=length - x
            x= random.randint(1,15)

        for i in range(length):
            if x_offset>47:
                track.append([1,0,random.randint(10,12)/100.0])
            else:
                track.append([1, 0, random.randint(13, 14)/100.0])
        return track

上面是两种获取移动轨迹的方式,大家可以自己试一下,那个效率更高。

最后就是控制滑块去滑动了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def move_to_gap(self, slider, track):
    """
    拖动滑块到缺口处
    :param slider: 滑块
    :param track: 轨迹
    :return:
    """
    ActionChains(self.browser).click_and_hold(slider).perform()
    while track:
        x = random.choice(track)
        ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
        track.remove(x)
    tracks = [-3, -3, -3, -2, -2, -2, -2, -2, -1, -1, -1, -1]
    time.sleep(0.5)

    for track in tracks:
        ActionChains(self.browser).move_by_offset(xoffset=track, yoffset=0).perform()
    # 小范围震荡一下,进一步迷惑极验后台,这一步可以极大地提高成功率
    ActionChains(self.browser).move_by_offset(xoffset=-1, yoffset=0).perform()
    ActionChains(self.browser).move_by_offset(xoffset=1, yoffset=0).perform()

    time.sleep(0.5)
    ActionChains(self.browser).release().perform()
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def simulate_drag(self, track):

        dom_div_slider = self.browser.find_element_by_xpath('//*[@id="gc-box"]/div/div[3]/div[2]')

        ActionChains(self.browser).click_and_hold(on_element=dom_div_slider).perform()

        for x,y,z in track:
            ActionChains(self.browser).move_to_element_with_offset(
                to_element=dom_div_slider,
                xoffset=x+22,
                yoffset=y+22).perform()
            time.sleep(z)

        time.sleep(0.9)
        ActionChains(self.browser).release(on_element=dom_div_slider).perform()
        time.sleep(1)
        dom_div_gt_info = self.browser.find_element_by_class_name('gt_info_type')
        return dom_div_gt_info.text

试试两种不同的滑动方式有什么不同

方法都给大家了,大家可以自己多试试,找出最高效的滑动方式,

如果碰到其他的滑动验证码只需修改元素的定位,思路一样

关于ActionChains,不懂的就去查查

最后源码地址:https://github.com/AndrewAndrea/check_img_code

不要忘了star, 谢谢!

有问题可以留言

抖音剩下的下次的更新,如何破解api,还有appnium 的使用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python爬虫scrapy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
安装服务启动报错Failed to get D-Bus connection: Operation not permitted
今天别人给我了一个 linux 主机的远程登录方式,让我上去帮他安装个 docker。这么简单的事情不是手到擒来吗。于是开始搞
张琳兮
2021/02/24
13.8K0
Centos7 将home空间分配给根目录(/dev/centos/root)
根据:Free PE / Size 33159 / <129.53 GiB判断 可用空间为129.53 GiB
IT小马哥
2024/09/29
6130
K8s上用cephfs存储
前言 k8s对ceph rbd模式不支持ReadWriteMany(RWX),为了满足k8s的灵活性需求,采用支持多点挂载的cephfs工作模式
院长技术
2020/06/11
1.4K0
JAVA 应用线上故障排查手册
线上故障主要会包括 CPU、磁盘、内存(含JVM)以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍。 基本上出问题就是 df、free、top、jstack、jmap具体问题具体分析
IT运维技术圈
2022/10/24
6940
一个轻量的Linux运维监控脚本
下面就脚本和小伙伴简单介绍下,如果小伙伴也有我这样的情况,可以参考。主要监控信息有以下几部分内容
山河已无恙
2023/03/02
1.5K0
一个轻量的Linux运维监控脚本
Docker容器学习梳理-容器硬盘热扩容
前面已介绍了docker很多知识点的操作记录,今天这里梳理下docker容器空间扩展的操作。默认情况下,docker容器的空间是10G。在实际生产环境下,对docker容器进行热扩容(动态扩容)是非常重要的一个需求。 Docker容器动态扩展的优点: 1)不需要修改docker配置,不需要重启docker服务; 2)可以直接对运行中的容器进行动态扩展(只能增,无法缩); Docker容器动态扩展的条件: 1)docker所在宿主机分区的格式必须是ext2、ext3、ext4; 2)docker存储引擎必
洗尽了浮华
2018/01/23
3.2K0
docker服务器出现/opt/n-bash: 无法为立即文档创建临时文件: 设备上没有空间问题
可看到如下结果: 文件系统 类型 容量 已用 可用 已用% 挂载点 /dev/mapper/cl-root xfs 37G 37G 20K 100% / devtmpfs devtmpfs 7.8G 0 7.8G 0% /dev tmpfs tmpfs 7.8G 84K 7.8G 1% /dev/shm tmpfs tmpfs
SL_World
2021/09/18
1.7K0
索引构建磁盘IO太高,巧用tmpfs让内存来帮忙
在文本索引构建这种需要大量占用磁盘IO的任务,如果正巧你的内存还有点余粮,是否可以先索引存储到内存,然后再顺序写入到磁盘呢?,需要大量占用磁盘IO,如果正巧你的内存还有点余粮,是否可以先索引存储到内存,然后再顺序写入到磁盘呢?
JadePeng
2024/02/07
1960
索引构建磁盘IO太高,巧用tmpfs让内存来帮忙
Centos缩容home磁盘空间到根目录/下操作
自己在家里老笔记搭建的CentOS7系统用来跑一些服务,前段时间通过samba共享存储把小米摄像头视频进行实时转存到笔记本上,最近发现磁盘不足了,因为我默认是挂载到根目录下的,以前安装操作系统时把所有空间分配给了/home目录下,现在根目录的磁盘空间,又不想更改目录,所以打算把/home目录的空间腾出挂载给根目录,于是有了本篇文章。
Lcry
2022/11/29
2.1K0
springboot第49集:【思维导图】多线程,常用类与基础API,集合框架,泛型,数据结构源码...
在继承Thread类的方式中,同步监视器要慎用this,可以考虑使用:当前类.class。
达达前端
2024/01/17
3250
springboot第49集:【思维导图】多线程,常用类与基础API,集合框架,泛型,数据结构源码...
Docker疑难杂症汇总一
来源:https://www.escapelife.site/posts/43a2bb9b.html
入门笔记
2022/06/03
7700
Docker疑难杂症汇总一
docker - 占满根目录空间的解决方案
Docker 默认会占用根目录的空间,时间久了就会吧根目录占满,本文记录解决方案。 问题复现 不知不觉根目录已经没有空间,ls 的补全都会报错。 cannot create temp file for here-document: No space left on devic 可以看到 /已经没有空间了 $ df -h Filesystem Size Used Avail Use% Mounted on udev
为为为什么
2022/08/05
1.6K0
docker技术入门与精通(2020.12笔记总结)
大家好,又见面了,我是全栈君。 一.docker基本概念和框架 1.docker简介 docker:将引用程序自动部署到容器 2. docker info 显示docker 信息 3.docker Linux安装方法 并将当前用户加入docker用户组,不必须用sudo开头 docker安装后报错 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon run
全栈程序员站长
2022/07/18
4960
docker技术入门与精通(2020.12笔记总结)
Kubernetes(k8s)之分布式文件系统glusterfs
答:使用持久化存储nfs,但是使用nfs这个共享存储特别简单,但是后期在扩容和管理方面都特别的不方便,在生产中一般都是使用分布式文件系统,这里使用的是分布式文件系统glusterfs。
别先生
2020/07/06
1.4K0
Kubernetes(k8s)之分布式文件系统glusterfs
迁移 Docker 容器储存位置
本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)
soulteary
2019/09/27
2.3K0
GlusterFS分布式存储集群部署记录-相关补充
接着上一篇Centos7下GlusterFS分布式存储集群环境部署记录文档,继续做一些补充记录,希望能加深对GlusterFS存储操作的理解和熟悉度。 ========================清理glusterfs存储环境========================= 由上面可知,该glusterfs存储集群有四个节点: [root@GlusterFS-master ~]# cat /etc/hosts ....... 192.168.10.239 GlusterFS-master 192.1
洗尽了浮华
2018/04/19
1.9K0
CentOS 8合并home分区到root
新装CentOS的时候,选择了默认分区方案。300G的硬盘,装完后发现默认会分配50G到/root目录下,然后分配一些其他的目录,剩下的都会分配给/home目录。
Qwe7
2022/01/30
1.5K0
Docker是如何实现隔离的
容器化技术在当前云计算、微服务等体系下大行其道,而 Docker 便是容器化技术的典型,对于容器化典型的技术,我们有必要弄懂它,所以这篇文章,我会来分析下 Docker 是如何实现隔离技术的,Docker 与虚拟机又有哪些区别呢?接下来,我们开始逐渐揭开它的面纱。
xcbeyond
2020/06/19
1.9K0
Docker是如何实现隔离的
Docker Storage Driver - Overlay2
目前有多种文件系统可以被当作联合文件系统,实现如上的功能:overlay2,aufs,devicemapper,btrfs,zfs,vfs等等。而overlay2是docker目前推荐的文件系统:https://docs.docker.com/storage/storagedriver/select-storage-driver/
后端云
2022/11/25
7220
Docker Storage Driver - Overlay2
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
这些字段是用于描述ifstat命令输出结果中的网络接口的信息。下面是对这些字段的介绍:
刘大猫
2024/11/04
1780
推荐阅读
相关推荐
安装服务启动报错Failed to get D-Bus connection: Operation not permitted
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档