百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

python验证码识别,极验滑动验证码识别

off999 2024-10-23 12:52 36 浏览 0 评论

一:极验滑动验证码简介

??近些年来出现了一些新型验证码,不想旧的验证码对人类不友好,但是这种验证码对于代码来说识别难度上升了几个等级。因此需要其他的手段进行处理。
??识别需要的python库:selenium和ChromeDriver驱动,不同浏览器的要下载的驱动库不同。
?
??极验滑动验证码已经到了3.0版本,相关于图形验证码识别难度更大,原理是拖动图片到缺口处,然后拼合图像进行验证,会生成三个加密参数,通过表单提交到后台,后台再进行验证。
??极验验证码还增加了机器学习的方法来识别是否是恶意程序进行识别,有防模拟,防伪造,防暴力的方式, 只需0.4秒,并且保护资源不被滥用和盗取。
??我们的程序一般只要不是恶意进行爬取的,并遵守爬虫协议,就可以。千万不要给服务器造成负担。

二:极验滑动验证码识别思路

??这里我们可以采用模拟浏览器动作的方式完成验证,用Selenium来完全模拟人的行为完成验证。
??主要分为三步
??(1)模拟点击验证按钮
??(2)识别滑动缺口的位置
??(3)模拟拖动滑块
??第(1)步还比较好说,第(2)步操作识别接口的位置比较关键,需要用到图像处理看到接口的位置,并和原图对比检测的方法来识别缺口的位置。同时获取两张图片,设定一个对比阈值,然后遍历两张图片,找出相同像素RGB差距超过此阈值的像素点,那么像素点位置就是缺口的位置。
??第(3)步较难,由于人的移动轨迹是先加速后减速,匀速移动和随机移动等方法都不能通过验证,要模拟好这个过程。

三:极验验证码识别

1.极验验证码官网

官网图片为:

2.初始化配置

# 注册的用户名和密码
email = ''
password = ''

class CrackGeetest():
 def __init__(self):
 self.url = 'https://account.geetest.com/login'
 self.browser = webdriver.Chrome()
 self.wait = WebDriverWait(self.browser, 20)
 self.email = email
 self.password = password

3.模拟点击

??识别验证码第一步就是模拟点击初始的验证按钮,用显式等待的方法进行获取。

def get_geetest_button(self):
 """
 获取初始验证按钮
 返回值:按钮对象
 """
 button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))
 return button

??在调用位置即可模拟点击:

# 点击验证按钮
button = self.get_geetest_button()
button.click()

4.识别缺口

??接下来识别缺口的位置,首先获取两张图片,进行对比,不一样的位置就是缺口。
??获取不带缺口的图片。用selenium选取图片元素得到整个网页的截图然后裁剪即可,代码如下:

def get_screenshot(self):
 """
 获取网页截图
 :return: 截图对象
 """
 screenshot = self.browser.get_screenshot_as_png()
 screenshot = Image.open(BytesIO(screenshot))
 return screenshot

 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_image(self, name='captcha.png'):
 """
 获取验证码图片
 :return: 图片对象
 """
 top, bottom, left, right = self.get_position()
 print('验证码位置', top, bottom, left, right)
 screenshot = self.get_screenshot()
 captcha = screenshot.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

??用click()即可触发点击,如下:

# 点按呼出缺口
slider = self.get_slider()
slider.click()

??接下来就是通过对比图片获取缺口,通过遍历图片上的每个坐标点,获取两张图片对应像素点的RGB数据。如果在一定范围内,那就代表两个像素相同,继续对比下一个像素点。如果差距超过一定范围,则代表像素点不同,当前位置就是缺口位置。通过设置一个阈值threshold,来进行判断,代码如下:

def is_pixel_equal(self, image1, image2, x, y):
 """
 判断两个像素是否相同
 :param image1: 图片1
 :param image2: 图片2
 :param x: 位置x
 :param y: 位置y
 :return: 像素是否相同
 """
 # 取两个图片的像素点
 pixel1 = image1.load()[x, y]
 pixel2 = image2.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, image1, image2):
 """
 获取缺口偏移量
 :param image1: 不带缺口图片
 :param image2: 带缺口图片
 :return:
 """
 left = 60
 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):
 left = i
 return left
 return left

5.模拟拖动

??模拟拖动并不复杂,但是里面的细节比较多。用相关的函数将滑块拖动到对应的位置即可。但是要是匀速拖动,会必然识别出是程序,非人类操作,因为人类无法做到完全匀速拖动,会识别出是机器操作,使得验证码失败。
??通过不同的方法检测,我们发现把前段滑块做匀加速运动,后段滑块做匀减速运动,即可完成验证。
??这里加速度用a来表示,当前速度用v表示,初速度用vo表示,位移用x表示,时间用t表示。
??代码如下:

def get_track(self, distance):
 """
 根据偏移量获取移动轨迹
 :param distance: 偏移量
 :return: 移动轨迹
 """
 # 移动轨迹
 track = []
 # 当前位移
 current = 0
 # 减速阈值
 mid = distance * 4 / 5
 # 计算间隔
 t = 0.2
 # 初速度
 v = 0
 
 while current < distance:
 if current < mid:
 # 加速度为正2
 a = 2
 else:
 # 加速度为负3
 a = -3
 # 初速度v0
 v0 = v
 # 当前速度v = v0 + at
 v = v0 + a * t
 # 移动距离x = v0t + 1/2 * a * t^2
 move = v0 * t + 1 / 2 * a * t * t
 # 当前位移
 current += move
 # 加入轨迹
 track.append(round(move))
 return track
 
 def move_to_gap(self, slider, track):
 """
 拖动滑块到缺口处
 :param slider: 滑块
 :param track: 轨迹
 :return:
 """
 ActionChains(self.browser).click_and_hold(slider).perform()
 for x in track:
 ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
 time.sleep(0.5)
 ActionChains(self.browser).release().perform()

6:全部代码

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

EMAIL = 'cqc@cuiqingcai.com'
PASSWORD = ''
BORDER = 6
INIT_LEFT = 60

# 注册的用户名和密码
email = ''
password = ''


class CrackGeetest():
 def __init__(self):
 self.url = 'https://account.geetest.com/login'
 self.browser = webdriver.Chrome()
 self.wait = WebDriverWait(self.browser, 20)
 self.email = email
 self.password = password
 
 def __del__(self):
 self.browser.close()
 
 def get_geetest_button(self):
 """
 获取初始验证按钮
 返回值:按钮对象
 """
 button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))
 return button
 
 def get_screenshot(self):
 """
 获取网页截图
 :return: 截图对象
 """
 screenshot = self.browser.get_screenshot_as_png()
 screenshot = Image.open(BytesIO(screenshot))
 return screenshot

 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_image(self, name='captcha.png'):
 """
 获取验证码图片
 :return: 图片对象
 """
 top, bottom, left, right = self.get_position()
 print('验证码位置', top, bottom, left, right)
 screenshot = self.get_screenshot()
 captcha = screenshot.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 open(self):
 """
 打开网页输入用户名密码
 :return: None
 """
 self.browser.get(self.url)
 email = self.wait.until(EC.presence_of_element_located((By.ID, 'email')))
 password = self.wait.until(EC.presence_of_element_located((By.ID, 'password')))
 email.send_keys(self.email)
 password.send_keys(self.password)
 
 def is_pixel_equal(self, image1, image2, x, y):
 """
 判断两个像素是否相同
 :param image1: 图片1
 :param image2: 图片2
 :param x: 位置x
 :param y: 位置y
 :return: 像素是否相同
 """
 # 取两个图片的像素点
 pixel1 = image1.load()[x, y]
 pixel2 = image2.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, image1, image2):
 """
 获取缺口偏移量
 :param image1: 不带缺口图片
 :param image2: 带缺口图片
 :return:
 """
 left = 60
 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):
 left = i
 return left
 return left
 
 def get_track(self, distance):
 """
 根据偏移量获取移动轨迹
 :param distance: 偏移量
 :return: 移动轨迹
 """
 # 移动轨迹
 track = []
 # 当前位移
 current = 0
 # 减速阈值
 mid = distance * 4 / 5
 # 计算间隔
 t = 0.2
 # 初速度
 v = 0
 
 while current < distance:
 if current < mid:
 # 加速度为正2
 a = 2
 else:
 # 加速度为负3
 a = -3
 # 初速度v0
 v0 = v
 # 当前速度v = v0 + at
 v = v0 + a * t
 # 移动距离x = v0t + 1/2 * a * t^2
 move = v0 * t + 1 / 2 * a * t * t
 # 当前位移
 current += move
 # 加入轨迹
 track.append(round(move))
 return track
 
 def move_to_gap(self, slider, track):
 """
 拖动滑块到缺口处
 :param slider: 滑块
 :param track: 轨迹
 :return:
 """
 ActionChains(self.browser).click_and_hold(slider).perform()
 for x in track:
 ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
 time.sleep(0.5)
 ActionChains(self.browser).release().perform()
 
 def login(self):
 """
 登录
 :return: None
 """
 submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-btn')))
 submit.click()
 time.sleep(10)
 print('登录成功')
 
 def crack(self):
 # 输入用户名密码
 self.open()
 # 点击验证按钮
 button = self.get_geetest_button()
 button.click()

 # 获取验证码图片
 image1 = self.get_geetest_image('captcha1.png')
 # 点按呼出缺口
 slider = self.get_slider()
 slider.click()
 # 获取带缺口的验证码图片
 image2 = self.get_geetest_image('captcha2.png')
 # 获取缺口位置
 gap = self.get_gap(image1, image2)
 print('缺口位置', gap)
 # 减去缺口位移
 gap -= BORDER
 # 获取移动轨迹
 track = self.get_track(gap)
 print('滑动轨迹', track)
 # 拖动滑块
 self.move_to_gap(slider, track)
 
 success = self.wait.until(
 EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '验证成功'))
 print(success)
 
 # 失败后重试
 if not success:
 self.crack()
 else:
 self.login()


if __name__ == '__main__':
 crack = CrackGeetest()
 crack.crack()

这种方法对于不同的极验滑动验证码来说都适用,关键在于识别的思路,如何识别缺口位置,如何生成运动轨迹等。之后遇到类似的验证码,都可以这样进行识别。

最后,小编想说:我是一名python开发工程师,整理了一套最新的python系统学习教程,想要这些资

料的可以关注私信小编“01”即可,希望能对你有所帮助。

相关推荐

u盘启动杀毒软件(u盘杀毒系统)

  有,但是主要是专杀工具,全面的综合杀毒软件基本上没有,因为没什么用。  1、放在U盘里的杀毒软件,就是不安装,也不监控,只杀毒的软件。  2、目前的杀毒软件的工作机制,主要是监控,监控电脑不感染病...

联想维修站点查询官网(联想 维修 服务网点)

您可以在联想的官方网站上查询到附近的授权维修服务点,或者拨打联想的客服电话寻求帮助。在维修服务点,您可以享受到专业的维修服务,包括硬件故障、软件问题、系统优化等方面的维护和维修。维修人员将会根据您的电...

怎么登录hotmail邮箱(邮箱登陆hotmail)
  • 怎么登录hotmail邮箱(邮箱登陆hotmail)
  • 怎么登录hotmail邮箱(邮箱登陆hotmail)
  • 怎么登录hotmail邮箱(邮箱登陆hotmail)
  • 怎么登录hotmail邮箱(邮箱登陆hotmail)
电脑不识别移动硬盘(移动硬盘灯亮但不读取)

电脑不能识别移动硬盘可能是由于以下原因造成的:1.电脑和硬盘之间的连接首先,可以确保移动硬盘正确连接到电脑上,检查USB接口是否松动或损坏,可以尝试更换USB线或者尝试连接到其他USB接口看是否能够...

键盘的win键在哪里(电脑键盘的win键在哪里)

win键就是电脑键盘上显示WINDOWS标志的按键。位于CTRL键与ALT键两个键之间,win键的具体位置一般电脑键盘上有左右两个。Windows键是一种特殊的键,通常位于键盘的左下角。它的图案是一个...

新手学做ppt(新手学做ppt的软件有哪些)
  • 新手学做ppt(新手学做ppt的软件有哪些)
  • 新手学做ppt(新手学做ppt的软件有哪些)
  • 新手学做ppt(新手学做ppt的软件有哪些)
  • 新手学做ppt(新手学做ppt的软件有哪些)
ghost全盘备份步骤图(用ghost怎么进行全盘备份)

可以用手动备份到指定分区。一、用一键Ghost还原中的“中文向导”备份开始-程序-一键Ghost-选出“中文向导”,Ghost中文向导-1、备份文件默认是“第1硬盘第1分区”,如果不是,将鼠标指针移...

键盘的windows键是哪一个(键盘上windows键是哪个键)
键盘的windows键是哪一个(键盘上windows键是哪个键)

windows键就是电脑键盘上ctrl键和alt键之间的按键,位于左下角。它带着微软的徽标,跟开始菜单一样的图标,它属于辅助按键,主要与其它按键组合使用,实现一些特定的功能,组合成多种快捷操作方式。这里上面所知的Win键其实就是键盘上的Wi...

2025-12-31 10:51 off999

win10打开设置快捷键(win10打开设置快捷键是什么)

1、首先打开电脑,在任务栏的语言地方点击一下再点击语言首选项。2、然后在新的界面里点击选择左侧“高级设置”按钮。3、之后在新的界面里点击选择“更改语言栏热键”按钮。4、然后在新的界面里点击选择“更改热...

flash插件下载手机版下载安装

华为手机的最新系统版本已经不再支持FlashPlayer,这是由于Adobe已于2020年底停止更新和支持FlashPlayer。因此,如果您使用最新的华为手机系统,可能无法安装和使用Flash...

官方应用商店下载(小米官方应用商店下载)

1.审核和验证:应用商店会对应用进行审核和验证,确保其质量和可靠性。开发者需要满足一定的要求才能在应用商店上架应用。而官网下载的应用没有经过此类审核和验证,因此用户需要自行评估其质量和可信度。2....

主题软件免费(主题软件免费推荐)

下载主题方法:一、打开手机找到APPStore应用软件,二、点击进去在下面找到有个搜索,点击它查找主题壁纸,三、弹出来很多主题壁纸,根据下载量和个人喜欢的应用主题选择下载相应的主题,四、下载成功后即...

一芯fc1178bc盘量产教程(一芯量产工具使用教程)

fc1178bc量产工具没有显示u盘拔下U盘,关闭量产工具,再插上U盘(先要确认卸载了安国的驱动,如果不能确认,运行LoadDriver.exe卸载),然后插上U盘,右键我的电脑---属性---硬件-...

电脑怎么样还原原来的系统(电脑怎么还原之前的系统版本)
  • 电脑怎么样还原原来的系统(电脑怎么还原之前的系统版本)
  • 电脑怎么样还原原来的系统(电脑怎么还原之前的系统版本)
  • 电脑怎么样还原原来的系统(电脑怎么还原之前的系统版本)
  • 电脑怎么样还原原来的系统(电脑怎么还原之前的系统版本)
u盘内文件损坏怎么办(u盘内文件损坏怎么办解决)

以下是8种修复U盘文件损坏的方法:1.风险自担型:试图直接复制文件如果U盘的部分文件损坏,您可能可以使用此方法。请复制文件您能打开的所有文件,并尝试将它们粘贴到桌面或其他文件夹中。但是请...

取消回复欢迎 发表评论: