爬虫—GEETEST滑动验证码识别
一、准备工作
本次使用Selenium,浏览器为Chrome,并配置好ChromDriver
二、分析
1.模拟点击验证按钮:可以直接使用Selenium完成。
2.识别滑块的缺口位置:先观察图片中缺口的位置以及周围边缘,利用原图与其对比检测来识别缺口位置。
同时获取原图与缺口图片,设定一个对比阀值,然后对两张图片进行遍历,找出相同位置像素RGB差距超过此阀值的像素点。即缺口的位置
3.模拟拖动滑块:极验增加了机械轨迹识别与速度检测,只有完全模拟人的操作才能通过验证。运动轨迹一般先加速,然后在减速。
三,代码实现
1.初始化
使用魅族登陆注册页面进行测试,https://i.flyme.cn/register?。在这里先初始化一些配置

import time
from io import BytesIO
from PIL import Image
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC phone = '' class GeetestSpider(): def __init__(self):
self.url = "https://i.flyme.cn/register?"
self.browser =webdriver.Chrome(executable_path=r'D:\Google\Chrome\Application\chromedriver')
self.wait = WebDriverWait(self.browser, 20)
self.phone = phone
2.模拟点击
def get_button(self):
"""
获取初始验证按钮,模拟点击
:return:按钮对象
"""
button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))
return button
3.识别缺口
获取前后两张比对图片,不一致的地方即为缺口位置。利用Selenium获取图片元素,得到位置和宽高,然后获取整个网页的截图,再将图片剪裁出来即可。
def get_screen_image(self):
"""
获取网页截图
:return: 截图对象
"""
screen_img = self.browser.get_screenshot_as_png()
screen_img = Image.open(BytesIO(screen_img))
return screen_img def get_position(self):
"""
获取验证码的位置
:return: 验证码位置元祖
"""
img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))
time.sleep(2)
location = img.location
size = img.size
top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[
'width']
return top, bottom, left, right def get_geetest_img(self, name='captcha.png'):
"""
获取验证码图片
:return: 图片对象,Image对象
"""
top, bottom, left, right = self.get_position()
print('验证码位置:', top, bottom, left, right)
screen_img = self.get_screen_image()
# 剪裁图片
captcha = screen_img.crop((left, top, right, bottom))
captcha.save(name)
return captcha def get_slider(self):
"""
获取滑块
:return:滑块对象
"""
slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
return slider
获取滑块slider之后,调用click()方法即可触发点击,缺口图片就好呈现出来。再调用get_geetest_img()方法将获取第二章图片。
将获取到的两张图片分别赋值给img1,img2。进行图片对比,遍历图片的每个坐标点,获取两张图片对应像素点的RGB数据。如果二者的RGB数据差在一定的范围内,则代表两个像素相同,继续进行下一个点的对比。如果差距超过一定范围,则代表像素点不相同,即缺口的位置。
def equal_rgb(self, img1, img2, x, y):
"""
判断两个像素点是否相同
:param img1: 图片1
:param img2: 图片2
:param x: 位置x
:param y: 位置y
:return: 是否相同
"""
# 获取两张图片的像素点
pixel1 = img1.load()[x, y]
pixel2 = img2.load()[x, y]
threshold = 60
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 def get_gap(self, img1, img2):
"""
获取偏移量
:param img1:不带缺口的图片
:param img2: 带缺口的图片
:return: 偏移量
"""
left = 60
for i in range(left, img1.size[0]):
for j in range(img1.size[1]):
if not self.equal_rgb(img1,img2,i,j):
left = i
return left
return left
4.模拟拖动滑块
为了模拟人的操作,滑块的拖动速度不应该是匀速,也不应该是保持在某一速度上下抖动。滑块的速度变化应该是一开始在加速,接近缺口就会减速,想象一下我们手动拖动滑块的情况。
滑块的加速度用a表示,当前速度用v表示,初始速度用v0表示,移动距离用x表示,运动时间t表示,满足以下关系:
x = v0 * t + a * t * t / 2
v = v0 + a * t
def get_track(self, d):
"""
根据偏移量获取运动轨迹
:param d: 偏移量
:return: 运动轨迹,每次移动距离
"""
# 运动轨迹
track = []
# 当前位移
current = 0
# 开始减速的偏移量,设位移达到偏移量的2/3时开始减速
deviation = d * 2 / 3
# 间隔时间
t = 0.2
# 初始速度
v = 0 while current < d:
if current < deviation:
# 加速阶段
a = 2
else:
# 减速阶段
a = -2 # 初始速度
v0 = v
# 当前速度
v = v0 + a * t
# 位移
move = v0 * t + a * t * t / 2
# 当前位移
current += move
# 添加到轨迹,保留整数
track.append(round(move))
return track def move_slider(self, slider, track):
"""
按照轨迹移动滑块至缺口
:param slider:滑块
:param track: 轨迹
:return:
"""
# 鼠标按住滑块
ActionChains(self.browser).click_and_hold(slider).perform()
for i in track:
# 遍历轨迹元素,每次移动对应位移
ActionChains(self.browser).move_by_offset(xoffset=i, yoffset=0).perform()
time.sleep(0.5)
# 移动完成后,松开鼠标
ActionChains(self.browser).release().perform()
验证成功:

5.完整代码
# _*_ coding=utf-8 _*_ import time
from io import BytesIO
from PIL import Image
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC # 初始化
class GeetestSpider():
def __init__(self):
self.url = "https://i.flyme.cn/register"
self.browser = webdriver.Chrome(executable_path=r'D:\Google\Chrome\Application\chromedriver')
self.wait = WebDriverWait(self.browser, 20) def get_button(self):
"""
获取初始验证按钮,模拟点击
:return:按钮对象
"""
button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip_content')))
return button def get_screen_image(self):
"""
获取网页截图
:return: 截图对象
"""
screen_img = self.browser.get_screenshot_as_png()
screen_img = Image.open(BytesIO(screen_img))
return screen_img def get_position(self):
"""
获取验证码的位置
:return: 验证码位置元祖
"""
img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))
time.sleep(2)
location = img.location
size = img.size
top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[
'width']
return top, bottom, left, right def get_geetest_img(self, name='captcha.png'):
"""
获取验证码图片
:return: 图片对象,Image对象
"""
top, bottom, left, right = self.get_position()
print('验证码位置:', top, bottom, left, right)
screen_img = self.get_screen_image()
# 剪裁图片
captcha = screen_img.crop((left, top, right, bottom))
captcha.save(name)
return captcha def get_slider(self):
"""
获取滑块
:return:滑块对象
"""
slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
return slider def equal_rgb(self, img1, img2, x, y):
"""
判断两个像素点是否相同
:param img1: 图片1
:param img2: 图片2
:param x: 位置x
:param y: 位置y
:return: 是否相同
"""
# 获取两张图片的像素点
pixel1 = img1.load()[x, y]
pixel2 = img2.load()[x, y]
threshold = 60
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 def get_gap(self, img1, img2):
"""
获取偏移量
:param img1:不带缺口的图片
:param img2: 带缺口的图片
:return: 偏移量
"""
# 直接从滑块的右侧开始遍历
left = 60
for i in range(left, img1.size[0]):
for j in range(img1.size[1]):
if not self.equal_rgb(img1, img2, i, j):
left = i
return left
return left def get_track(self, d):
"""
根据偏移量获取运动轨迹
:param d: 偏移量
:return: 运动轨迹,每次移动距离
"""
# 运动轨迹
track = []
# 当前位移
current = 0
# 开始减速的偏移量,设位移达到偏移量的2/3时开始减速
deviation = d * 2 / 3
# 间隔时间
t = 0.2
# 初始速度
v = 0 while current < d:
if current < deviation:
# 加速阶段
a = 2
else:
# 减速阶段
a = -2 # 初始速度
v0 = v
# 当前速度
v = v0 + a * t
# 位移
move = v0 * t + a * t * t / 2
# 当前位移
current += move
# 添加到轨迹,保留整数
track.append(round(move))
return track def move_slider(self, slider, track):
"""
按照轨迹移动滑块至缺口
:param slider:滑块
:param track: 轨迹
:return:
"""
# 鼠标按住滑块
ActionChains(self.browser).click_and_hold(slider).perform()
for i in track:
# 遍历轨迹元素,每次移动对应位移
ActionChains(self.browser).move_by_offset(xoffset=i, yoffset=0).perform()
time.sleep(0.5)
# 移动完成后,松开鼠标
ActionChains(self.browser).release().perform() def crack(self):
"""
模拟验证的各种操作
:return:None
"""
# 打开网站,输入注册手机号
self.browser.get(self.url)
self.wait.until(EC.presence_of_element_located((By.ID, 'phone')))
# 点击验证
button = self.get_button()
button.click()
# 获取验证码图片
img1 = self.get_geetest_img('captcha1.png')
# 获取滑块
slider = self.get_slider()
slider.click()
# 获取带缺口的图片
img2 = self.get_geetest_img('captcha2.png')
# 获取缺口位置
gap = self.get_gap(img1, img2)
print("缺口位置:", gap)
# 减去缺口位移
gap -= 6
# 获取轨迹
track = self.get_track(gap)
print("轨迹:", track)
# 拖动滑块
self.move_slider(slider, track) success = self.wait.until(
EC.text_to_be_present_in_element((By.ID, 'geetest_success_radar_tip_content'), '验证成功')) # 失败重试
if not success:
self.crack() if __name__ == '__main__':
crack = GeetestSpider()
crack.crack()
爬虫—GEETEST滑动验证码识别的更多相关文章
- python验证码识别(2)极验滑动验证码识别
目录 一:极验滑动验证码简介 二:极验滑动验证码识别思路 三:极验验证码识别 一:极验滑动验证码简介 近些年来出现了一些新型验证码,不想旧的验证码对人类不友好,但是这种验证码对于代码来说识别难度上 ...
- VUE中使用geetest滑动验证码
一,准备工作:服务端部署 下载文件gt.gs: https://github.com/GeeTeam/gt3-python-sdk 需要说明的是这里的gt.js文件,它用于加载对应的验证JS库. 1. ...
- Pyhthon爬虫其之验证码识别
背景 现在的登录系统几乎都是带验证手段的,至于验证的手段也是五花八门,当然用的最多的还是验证码.不过纯粹验证码识已经是很落后的东西了,现在比较多见的是滑动验证,滑动拼图验证(这个还能往里面加广告).点 ...
- Django中使用极验Geetest滑动验证码
一,环境部署 1.创建一个django测试项目 此处省略... 二,文档部署 1.下载安装python对应的SDK 使用命令从Github导入完整项目:git clone https://github ...
- 对极验geetest滑块验证码图片还原算法的研究
免责声明 本文章所提到的技术仅用于学习用途,禁止使用本文章的任何技术进行发起网络攻击.非法利用等网络犯罪行为,一切信息禁止用于任何非法用途.若读者利用文章所提到的技术实施违法犯罪行为,其责任一概由读者 ...
- 爬虫(十二):图形验证码的识别、滑动验证码的识别(B站滑动验证码)
1. 验证码识别 随着爬虫的发展,越来越多的网站开始采用各种各样的措施来反爬虫,其中一个措施便是使用验证码.随着技术的发展,验证码也越来越花里胡哨的了.最开始就是几个数字随机组成的图像验证码,后来加入 ...
- Python爬虫入门教程 57-100 python爬虫高级技术之验证码篇3-滑动验证码识别技术
滑动验证码介绍 本篇博客涉及到的验证码为滑动验证码,不同于极验证,本验证码难度略低,需要的将滑块拖动到矩形区域右侧即可完成. 这类验证码不常见了,官方介绍地址为:https://promotion.a ...
- Python爬虫教程:验证码的爬取和识别详解
今天要给大家介绍的是验证码的爬取和识别,不过只涉及到最简单的图形验证码,也是现在比较常见的一种类型. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻 ...
- 第三百四十三节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy模拟登陆和知乎倒立文字验证码识别
第三百四十三节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy模拟登陆和知乎倒立文字验证码识别 第一步.首先下载,大神者也的倒立文字验证码识别程序 下载地址:https://gith ...
随机推荐
- java IO 流关系图谱
学习io流最好明白其之间的 关联与转换关系 ,以下是笔者所划得 关系图谱,大框包含小框 ,小框是大框内的 请求参数,箭头是继承或实现. 清晰了其关联与包含关系后我们便很容易在现实中结合使用了 . 这是 ...
- javascript中的私有作用域
我们知道js中所有的块级作用域都是无效的,块级作用域内的变量,在外部仍然可以被读取,其实是申明在外部的.如何实现变量的私有化,只在块级作用域起效,避免污染全局的变量呢.而且,挂载在全局的变量很难被回收 ...
- ERROR in Cannot find module 'node-sass'
windows下,通过淘宝的npm镜像安装 npm install node-sass --registry=https://registry.npm.taobao.org (之前安装好过,一段时间没 ...
- 每天一点点之javascript(ES6) - Map对象
1.语法 键/值对的集合. mapObj = new Map() 注:集合中的键和值可以是任何类型.如果使用现有密钥向集合添加值,则新值会替换旧值. 2.属性下表列出了 Map 对象的属性和描述. 构 ...
- JVM探秘:jinfo查看JVM运行时参数
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 如何查看JVM运行时参数,对于线上JVM调优是很关键的,因为只有知道了当前使用的JVM ...
- 十五、CI框架之自动加载数据库
一.在config的autoload.php文件中,如果写入以下代码,那么在控制器中无需再次加载数据库了,相当于全局自动加载数据库了 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码 ...
- 实现VR直播的关键技术
VR是多媒体技术发展的必然趋势,人们所使用的信息载体从最早的文字.图像,到音视频,再到用VR,将事物的描述表达推向了极致,充分满足了沉浸性.互动性和构想性三大要素的需求.随着5G的商业化运营,VR有望 ...
- C#高级编程(第9版) 第08章 委托、lambda表达式和事件 笔记
本章代码分为以下几个主要的示例文件: 1. 简单委托 2. 冒泡排序 3. lambda表达式 4. 事件示例 5. 弱事件 引用方法 委托是寻址方法的.NET版本.在C++中函数 ...
- part9 公用图片画廊组件拆分
1.src中创建 common 再创建 gallery.然后gallery.vue 2.build 中webpack.base.conf 中配置更短路径 module.exports {}中 reso ...
- POJ 1325 && 1274:Machine Schedule 匈牙利算法模板题
Machine Schedule Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12976 Accepted: 5529 ...