滑动验证码
程序员文章站
2022-05-13 15:11:44
...
本文是使用极验滑动验证码的官网做的实验,没有账号的可以先注册一个账号 ,地址 :https://account.geetest.com/login
- 安装环境
- chromedriver 下载地址 可以根据自己chrome版本和系统自行下载
地址:http://chromedriver.storage.googleapis.com/index.html
查看chrome版本 和下载chromedriver页面:
将解压好的文件放入/usr/local/bin目录中,由于mac的很多目录都是隐藏的,所以我们按快捷键command+shift+g,在弹出的窗口输入/usr/local/bin,
就可以打开这个目录,接着将解压好的驱动放入此目录即可。
安装 selenium -
pip install selenium
- 安装 PIL 图片处理
当我们输入pip insall PIL时候会发现错误,没有这个模块。因为这个模块安装是以前版本,在命令行输入 pip install pillowpip install pillow
- 测试
打开小黑窗from
selenium
import
webdriver
from
PIL
import
Image
browser
=
webdriver.Chrome()
browser.get(
"http://www.baidu.com"
)
得到以下结果证明环境没问题 接下来开始写代码咯
- chromedriver 下载地址 可以根据自己chrome版本和系统自行下载
写代码:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time
from io import BytesIO
from PIL import Image
from selenium.webdriver import ActionChains
from selenium.common.exceptions import TimeoutException
import random
EMAIL = '@qq.com'
PASSWORD = '密码'
class CrackGeetest():
"""
初始化
"""
def __init__(self):
self.url = 'https://account.geetest.com/login'
self.browser = webdriver.Chrome()
self.wait = WebDriverWait(self.browser, 5)
self.email = EMAIL
self.password = PASSWORD
def __del__(self):
self.browser.close()
def open(self):
"""
输入用户及密码
"""
self.browser.get(self.url)
email_xpath = '//*[@id="base"]/div[2]/div/div[2]/div[3]/div/form/div[1]/div/div/input'
email = self.wait.until(EC.presence_of_element_located((By.XPATH, email_xpath)))
password_xpath = '//*[@id="base"]/div[2]/div/div[2]/div[3]/div/form/div[2]/div/div[1]/input'
password = self.wait.until(EC.presence_of_element_located((By.XPATH, password_xpath)))
email.send_keys(self.email)
password.send_keys(self.password)
def get_geetest_button(self):
"""
获取初始验证按钮
返回按钮对象
"""
button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))
return button
def get_position(self):
"""
获取验证码位置-为截取验证码准备
返回验证码位置元组
"""
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_screenshot(self):
"""[summary]
获取网页截图
"""
screenshot = self.browser.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
return screenshot
def get_geetest_image(self, name='captcha.png'):
"""
获取验证码图片
返回图片对象
"""
top, bottom, left, right = self.get_position()
screenshot = self.get_screenshot()
# 通过验证码图片的位置从网页截图上截取验证码
captcha = screenshot.crop((left, top, right, bottom))
captcha.save(name)
return captcha
def get_slider(self):
"""
获取滑块对象
"""
slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
return slider
def get_track(self, distance):
"""
根据偏移量获取移动轨迹
Arguments:
distance {[type]} -- 偏移量
"""
# 移动轨迹
track = []
# 当前位移
current = 0
# 减速阀值
mid = distance * 7 / 10
# 计算间隔
t = 0.15
# 初速度
v = 0
while current < distance:
if current < mid:
# 加速度为正
a = 2.1
else:
# 加速度为负
a = -4.8
# 初速度v0
v0 = v
# 当前速度 v = v0 + at
v = v0 + a * t
# 移动距离 x = v0t + 1/2*a*t*t
move = v0 * t + 1 / 2 * a * t * t
# 当前位移
current += move
# 加入轨迹
track.append(round(move, 2))
return track
def move_to_gap(self, slider, tracks):
"""[summary]
拖动滑块到缺口处
动作: 点击且不释放鼠标-拖拽图片到缺口-释放鼠标
Arguments:
slider {[type]} -- 滑块
tracks {[type]} -- 轨迹
"""
# 点击并按住滑块
ActionChains(self.browser).click_and_hold(slider).perform()
# 移动
for x in tracks:
ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
time.sleep(0.1)
# 释放滑块
ActionChains(self.browser).release().perform()
def login(self):
"""[summary]
登录
"""
submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-btn')))
submit.click()
time.sleep(1)
print('登录成功')
def is_try_again(self):
"""[summary]
判断是否能够点击重试
"""
button_text = self.browser.find_element_by_class_name('geetest_radar_tip_content')
text = button_text.text
if text == '尝试过多':
button = self.browser.find_element_by_class_name('geetest_reset_tip_content')
button.click()
def is_success(self):
"""[summary]
判断是否成功
"""
button_text2 = self.browser.find_element_by_class_name('geetest_success_radar_tip_content')
text2 = button_text2.text
if text2 == '验证成功':
return 1
return 0
def for_move(self, x_temp):
"""[summary]
循环拖动
"""
flag = 0
for i in range(0, 7):
gap = random.randint(16, 20) * i + x_temp
if gap < 40:
continue
print('预估计缺口位置: ', gap)
self.is_try_again()
slider = self.get_slider()
track = self.get_track(gap)
print('滑动轨迹: ', track)
# 拖动滑块
self.move_to_gap(slider, track)
time.sleep(3)
if self.is_success():
flag = 1
break
return flag
def *****(self):
"""[summary]
验证
"""
try:
# 输入用户和密码
self.open()
time.sleep(2)
# 点击验证按钮
button = self.get_geetest_button()
button.click()
# 获取验证码图片
image1 = self.get_geetest_image('captcha1.png')
flag = 0
while 1:
temp = random.randint(0, 2) # 将轨迹划分为2, 则有1/2的几率
if temp == 0:
print('预估左1/2: ')
flag = self.for_move(30)
else:
print('预估右1/2: ')
flag = self.for_move(120)
if flag == 1:
break
except TimeoutException as e:
self.*****()
# 成功,登录
self.login()
time.sleep(10)
if __name__ == "__main__":
***** = CrackGeetest()
*****.*****()
推荐阅读