Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)


Posted in Python onJanuary 29, 2021

一、滑块验证码简述

       有爬虫,自然就有反爬虫,就像病毒和杀毒软件一样,有攻就有防,两者彼此推进发展。而目前最流行的反爬技术验证码,为了防止爬虫自动注册,批量生成垃圾账号,几乎所有网站的注册页面都会用到验证码技术。其实验证码的英文为 CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart),翻译成中文就是全自动区分计算机和人类的公开图灵测试,它是一种可以区分用户是计算机还是人的测试,只要能通过 CAPTCHA 测试,该用户就可以被认为是人类。由此也可知道破解滑块验证码的关键即是让计算机更好的模拟人的行为,这也是破解的难点所在。

二、环境配置

1.安装

selenium 支持 python2.7 以及 python3.5 等主流 python 版本,其安装较为简单,有网的环境下,打开cmd输入即可自动安装:

pip install selenium

2.webdriver

selenium 安装完成后,下载所选浏览器的 webdriver,本文以 ChromeDriver为例,下载解压后切记将.exe文件放入对应Python应用程序的同级目录下,以确保将 webdriver 的路径添加至系统 PATH 变量中。同时还需将.exe文件放入Chrome应用程序的同级目录下,注意下载的ChromeDriver版本需与Chrome浏览器版本对应才可使用。ChromeDriver下载地址

3.相关库与模板

#图像处理标准库
from PIL import Image  
#web测试
from selenium import webdriver
#鼠标操作
from selenium.webdriver.common.action_chains import ActionChains
#等待时间 产生随机数 
import time,random

三、破解步骤

本文以春秋官网为例:

  • 保存滑块验证码原图到本地。
  • 利用selenium进入滑块验证码页面,截取所需页面图片。
  • 通过图片像素对比分析获取缺口位置与滑块移动距离。
  • 机器模拟人工滑动轨迹。

四、代码实现

首先通过selenium对网页元素爬取进入滑块验证码页面

#打开页面至屏幕最大尺寸
driver = webdriver.Chrome()
driver.get('https://account.ch.com/NonRegistrations-Regist')
driver.maximize_window()
#获取输入手机号码的表单
input1 = driver.find_element_by_name('phoneNumberInput')
# 输入注册号码
input1.send_keys(phoneNumber)
time.sleep(0.2)
#获取打开滑块验证码页面的元素
getcheck=driver.find_element_by_id('getDynamicPwd')
#点击进入滑块验证码页面
getcheck.click()

Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)

上周国内最大的验证码平台极验(GEETEST)进行了滑块验证码更新,向反爬虫又迈进了一步,新浪、斗鱼等使用极验验证码的各大网站页也随之更新,当然春秋也不例外,此次更新显然是针对了破解滑块验证码的关键痛点,在此之前点击获取验证码,出现滑块验证码界面之后并不会直接出现滑块,此时可对屏幕进行截图,当点击滑动圆球之后才会出现滑块与缺口,此时再次进行截图,即可根据两次截图的像素RGB值逐一遍历,找到缺口位置。但更新之后点击获取验证码,直接会出现滑块与缺口,如图1所见。问题来了,现在没有原图作为参照,怎么找到缺口位置呢???仔细一想,其实这个问题并不难,无非就是需要一张原图作为参照,经过观察发现每个网站的验证码背景图片不过区区几张,那么我们可以考虑通过人工滑动滑块,在成功拼图后出现完整原图的那一瞬间进行屏幕截图,将原图逐一截图保存至本地,再通过缺口图片与本地保存的原图进行像素RGB值匹配,原图岂不速速现出原形,缺口图圆球需滑至最右再进行截图,下文详细解释。

# 获取拖拽的圆球
slideblock = driver.find_element_by_class_name('geetest_slider_button')
# 鼠标点击圆球不松开
ActionChains(driver).click_and_hold(slideblock).perform()
# 将圆球滑至相对起点位置的最右边
ActionChains(driver).move_by_offset(xoffset=250, yoffset=0).perform()
time.sleep(0.4)
# 保存包含滑块及缺口的页面截图
driver.save_screenshot('D:\quekou.png')
# 放开圆球
ActionChains(driver).release(slideblock).perform()
#打开保存至本地的缺口页面截图
quekouimg=Image.open('d://quekou.png')
# 匹配本地对应原图
sourceimg=match_source(quekouimg)
def match_source(image):
  imagea=Image.open('d://source1.png')
  imageb=Image.open('d://source2.png')
  imagec=Image.open('d://source3.png')
  imaged=Image.open('d://source4.png')
  list=[imagea,imageb,imagec,imaged]
  #通过像素差遍历匹配本地原图
  for i in list:
    #本人电脑原图与缺口图对应滑块图片横坐标相同,纵坐标原图比缺口图大88px,可根据实际情况修改
    pixel1=image.getpixel((868,340))
    pixel2=i.getpixel((868,428))
    #pixel[0]代表R值,pixel[1]代表G值,pixel[2]代表B值
    if abs(pixel1[0]-pixel2[0])<5:
      return i
  return image

为了更快捷获取滑块移动距离,我们可以考虑将滑块先滑至最右端再进行截图,因为采用从左往右对比遍历的方式,采用这种方式能保证第一次获取到的便是缺口位置,由于滑块起点相同,此种方法可减少计算滑块大小这一步(毕竟滑块大小计算也是通过像素遍历,没必要再计算一次)。

# 获取缺口位置
visualstack=get_diff_location(sourceimg,quekouimg)
# 获取移动距离loc,827为滑块起点位置
loc=visualstack-827
# 计算滑块位移距离
def get_diff_location(image1,image2):
  #(825,1082)(335,463)为滑块图片区域,可根据实际情况修改
  for i in range(825,1082):
    for j in range(335,463):
      #遍历原图与缺口图像素值寻找缺口位置
      if is_similar(image1,image2,i,j)==False:
        return i
  return -1
# 对比RGB值得到缺口位置
def is_similar(image1,image2,x,y):
  pixel1=image1.getpixel((x, y+88))
  pixel2=image2.getpixel((x, y))
  # 截图像素也许存在误差,50作为容差范围
  if abs(pixel1[0]-pixel2[0])>=50 and abs(pixel1[1]-pixel2[1])>=50 and abs(pixel1[2]-pixel2[2])>=50:
    return False
  return True

接下来,破解滑块验证码最关键也最难的一步来了,机器模拟人工滑动轨迹,或许你可以精准滑动到缺口位置,但还是会被识别为机器被怪物吃掉拼图,本人在测试的时候也是一把辛酸泪,最后经过不断调试学习,得到一种通过率还OK的滑动轨迹算法,即采用物理加速度位移相关公式按照先快后慢的人工滑动规律进行轨迹计算,同时还采用了模拟人滑动超过了缺口位置再滑回至缺口的情况以使轨迹更契合人工滑动轨迹。由于项目时间有限,本人就没花过多时间研究了,如果想要99%通过率可以尝试机器学习,采集人工滑动轨迹进行曲线拟合的方法获取轨迹。

#滑块移动轨迹
def get_track(self,distance):
  track=[]
  current=0
  mid=distance*3/4
  t=random.randint(2,3)/10
  v=0
  while current<distance:
     if current<mid:
       a=2
     else:
       a=-3
     v0=v
     v=v0+a*t
     move=v0*t+1/2*a*t*t
     current+=move
     track.append(round(move))
  return track
# 生成拖拽移动轨迹,加3是为了模拟滑过缺口位置后返回缺口的情况
track_list=get_track(loc+3)
time.sleep(2)
ActionChains(driver).click_and_hold(slideblock).perform()
time.sleep(0.2)
# 根据轨迹拖拽圆球
for track in track_list:
  ActionChains(driver).move_by_offset(xoffset=track,yoffset=0).perform()
# 模拟人工滑动超过缺口位置返回至缺口的情况,数据来源于人工滑动轨迹,同时还加入了随机数,都是为了更贴近人工滑动轨迹
imitate=ActionChains(driver).move_by_offset(xoffset=-1, yoffset=0)
time.sleep(0.015)
imitate.perform()
time.sleep(random.randint(6,10)/10)
imitate.perform()
time.sleep(0.04)
imitate.perform()
time.sleep(0.012)
imitate.perform()
time.sleep(0.019)
imitate.perform()
time.sleep(0.033)
ActionChains(driver).move_by_offset(xoffset=1, yoffset=0).perform()
# 放开圆球
ActionChains(driver).pause(random.randint(6,14)/10).release(slideblock).perform()
time.sleep(2)
#务必记得加入quit()或close()结束进程,不断测试电脑只会卡卡西
driver.close()

至此,小白破解滑块验证码就算基本了结,整个步骤看起来挺简单的,但其中的坑大概只有实践才会知道,出BUG之后第一件事请认真检查你的代码,不要放过任何一个地方,参数、范围、返回值、取值等等,甚至可能是你最觉得没问题的地方,往往是问题所在……over

到此这篇关于Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)的文章就介绍到这了,更多相关Python Selenium破解滑块验证码内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python操作json数据的一个简单例子
Apr 17 Python
python socket 超时设置 errno 10054
Jul 01 Python
Python列出一个文件夹及其子目录的所有文件
Jun 30 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
Dec 20 Python
python创建列表和向列表添加元素的实现方法
Dec 25 Python
Python语言描述连续子数组的最大和
Jan 04 Python
Django 创建后台,配置sqlite3教程
Nov 18 Python
python实现提取COCO,VOC数据集中特定的类
Mar 10 Python
PyCharm License Activation激活码失效问题的解决方法(图文详解)
Mar 12 Python
Python如何使用paramiko模块连接linux
Mar 18 Python
keras中模型训练class_weight,sample_weight区别说明
May 23 Python
Python 详解通过Scrapy框架实现爬取百度新冠疫情数据流程
Nov 11 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
Jan 29 #Python
如何用python开发Zeroc Ice应用
Jan 29 #Python
详解Pymongo常用查询方法总结
Jan 29 #Python
Python3使用tesserocr识别字母数字验证码的实现
Jan 29 #Python
Python爬取梨视频的示例
Jan 29 #Python
使用Python封装excel操作指南
Jan 29 #Python
用OpenCV进行年龄和性别检测的实现示例
Jan 29 #Python
You might like
php array_slice函数的使用以及参数详解
2008/08/30 PHP
解析PHP中ob_start()函数的用法
2013/06/24 PHP
thinkphp的CURD和查询方式介绍
2013/12/19 PHP
美图秀秀web开放平台--PHP流式上传和表单上传示例分享
2014/06/22 PHP
javascript 获取元素位置的快速方法 getBoundingClientRect()
2009/11/26 Javascript
解析javascript 数组以及json元素的添加删除
2013/06/26 Javascript
js实现局部页面打印预览原理及示例代码
2014/07/03 Javascript
jQuery1.9.1源码分析系列(十六)ajax之ajax框架
2015/12/04 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
javascript修改浏览器title方法 JS动态修改浏览器标题
2017/11/30 Javascript
Vue表单控件绑定图文详解
2019/02/11 Javascript
vue input输入框关键字筛选检索列表数据展示
2020/10/26 Javascript
JavaScript判断浏览器运行环境的详细方法
2019/06/30 Javascript
如何利用nodejs自动定时发送邮件提醒(超实用)
2020/12/01 NodeJs
[01:03:41]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第一场 12.17
2020/12/19 DOTA
python中遍历文件的3个方法
2014/09/02 Python
python根据出生日期返回年龄的方法
2015/03/26 Python
Python学习小技巧之列表项的拼接
2017/05/20 Python
python 反向输出字符串的方法
2018/07/16 Python
python绘制规则网络图形实例
2019/12/09 Python
使用python快速实现不同机器间文件夹共享方式
2019/12/22 Python
解决matplotlib.pyplot在Jupyter notebook中不显示图像问题
2020/04/22 Python
python3.6.5基于kerberos认证的hive和hdfs连接调用方式
2020/06/06 Python
让IE支持HTML5的方法
2012/12/11 HTML / CSS
J2EE是技术还是平台还是框架
2016/08/14 面试题
采购助理岗位职责
2014/02/16 职场文书
购房意向书范本
2014/04/01 职场文书
C++程序员求职信
2014/05/07 职场文书
学校师德师风整改措施
2014/10/27 职场文书
2014年健康教育工作总结
2014/11/20 职场文书
教师节领导致辞
2015/07/29 职场文书
大学校园招聘会感想
2015/08/10 职场文书
2016年第29个世界无烟日宣传活动总结
2016/04/06 职场文书
vue3使用vue-router的完整步骤记录
2021/06/20 Vue.js
在项目中使用redis做缓存的一些思路
2021/09/14 Redis
Python使用MapReduce进行简单的销售统计
2022/04/22 Python