selenium解决滑块验证码(亲测有效)
要解决滑块验证码,⾸选我们得梳理⼀下思路。⾸先我们要想到的就是怎么把滑块拉过去,这就涉及到拉动的距离问题,也就是要⾸先要解决滑块和缺⼝之间的距离的计算;然后就是解决模拟拉动的过程,要考虑怎么模拟才能绕过验证,从⽽获得验证通过。看到站内有些朋友使⽤加速度和减速度以及模拟⿏标抖动等⼀系列动作,或许有些⽹站确实可以通过验证,但是在我模拟浦发登陆时是没有⽤的。所以需要使⽤⾃定义的滑动曲线来设计滑动轨迹。
⼀般来说计算offset有两个⽅法:1. 通过背景图和带有缺⼝图之间⽐对像素来确定,但是这种由于背景底⾊的原因我们不能保证offset计算很准确。但是通过⼿动调整,我这⾥登陆浦发银⾏时准确率可以在75%以上。 2. 通过下载图⽚然后去训练,由于这⽅⾯我不擅长,故⽽这⾥只介绍⼀下第⼀种⽅法。
我们需要⽤到的库有:BytesIO、Image。
这⾥直接上代码,由于注释写的⽐较详细,不再做介绍。
import time
import random
from io import BytesIO
from PIL import Image
from selenium.webdrivermon.action_chains import ActionChains
from fund_transactions.sliding_track import drag_and_drop
class SliderVerification(object):
def __init__(self, driver):
self.driver = driver
def get_screenshot(self):
"""
获取屏幕截图
"""
screenshot = _screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
return screenshot
def update_style(self):selenium怎么使用
"""
修改图⽚的style属性,显⽰⽆缺⼝的图⽚
"""
# js = 'document.querySelectorAll("canvas")[3].'
# 这⾥使⽤js去缺⼝,获得背景图
js = 'ElementsByClassName("geetest_canvas_fullbg geetest_fade geetest_absolute")[0].setAttribute("style","display:block")'
ute_script(js)
time.sleep(2)
def get_position(self):
"""
获取截取验证码时的四条边
"""
# 获取验证码图⽚对象
code_img = self.driver.find_element_by_xpath("//canvas[@class='geetest_canvas_slice geetest_absolute']")
time.sleep(2)
location = code_img.location
size = code_img.size
# 计算图⽚截取区域(左,上,右,下,的坐标值)
left, top, right, buttom = location['x'], location['y'], location['x'] + size['width'], \
location['y'] + size['height']
return left, top, right, buttom
def get_image(self):
"""
截取验证码图⽚
"""
# 获取验证码位置
position = _position()
print("postion_1:", position)
# 从屏幕截图中抠出有缺⼝的验证码图⽚
captcha1 = _screenshot().crop(position)
# 修改style属性,显⽰⽆缺⼝的验证码图⽚
self.update_style()
print("position_2:", position)
# 从屏幕截图中抠出⽆缺⼝的验证码图⽚
captcha2 = _screenshot().crop(position)
with open('captcha1.png', 'wb') as f1, open('captcha2.png', 'wb') as f2:
captcha1.save(f1)
captcha2.save(f2)
# 这⾥将调整为原来带有缺⼝的图⽚显⽰出来
js = 'ElementsByClassName("geetest_canvas_fullbg geetest_fade geetest_absolute")[0].setAttribute("style","display:none")'        ute_script(js)
time.sleep(2)
return captcha1, captcha2
@staticmethod
def is_pixel_equal(img1, img2, x, y):
"""
判断两张图⽚的同⼀像素点的RGB值是否相等
"""
pixel1, pixel2 = img1.load()[x, y], img2.load()[x, y]
# print(pixel1,pixel2)
# 设定⼀个⽐较基准
sub_index = 60
# ⽐较
if abs(pixel1[0] - pixel2[0]) < sub_index and abs(pixel1[1] - pixel2[1]) < sub_index and abs(
pixel1[2] - pixel2[2]) < sub_index:
return True
else:
return False
def get_gap_offset(self, img1, img2):
"""
获取缺⼝的偏移量
"""
x = int(img1.size[0] / 4.2)
for i in range(x, img1.size[0]):
for j in range(img1.size[1]):
# 两张图⽚对⽐,(i,j)像素点的RGB差距,过⼤则该x为偏移值
if not self.is_pixel_equal(img1, img2, i, j):
x = i
return x
return x
然后调⽤get_gap_offset⽅法就可以获得偏移量,⽽参数img1/img2使⽤get_img⽅法可以获取。
拿到了偏移量,下⾯就需要获取滑动的轨迹。
import numpy as np
from selenium.webdrivermon.action_chains import ActionChains
def ease_out_quad(x):
return 1 - (1 - x) * (1 - x)
def ease_out_quart(x):
return 1 - pow(1 - x, 4)
def ease_out_expo(x):
if x == 1:
return 1
else:
return 1 - pow(2, -10 * x)
def get_tracks(distance, seconds):
"""
:param distance: offset
:
param seconds: 拉动时间
:return:
"""
tracks = [0]
offsets = [0]
# print("np_value:", np.arange(0.0, seconds, 0.1))
for t in np.arange(0.0, seconds, 0.1):
offset = round(ease_out_quart(t / seconds) * distance)
tracks.append(offset - offsets[-1])
offsets.append(offset)
return offsets, tracks
def drag_and_drop(browser, offset, knob):
"""
拖拽
:param browser: 浏览器对象
:param offset: 滑块到缺⼝的距离
:param knob: 滑块的位置
"""
offsets, tracks = get_tracks(offset, 12)
# print("offsets:", offsets)
# print("tracks:", tracks)
ActionChains(browser).click_and_hold(knob).perform()
for x in tracks:
ActionChains(browser).move_by_offset(x, 0).perform()
ActionChains(browser).pause(0.5).release().perform()
然后万事具备,就开始拉动滑块吧。下⾯这段代码应该放在第⼀段代码下⾯,第⼆段代码再第⼀段中有引⼊,所以这⾥直接调⽤。
def do_captcha(self):
"""
实现处理验证码
"""
# 有缺⼝,⽆缺⼝图⽚
time.sleep(3)
img1, img2 = _image()
# ⽐较两个验证码图⽚获取验证码滑块的偏移量
offset = _gap_offset(img1, img2)
offset = offset - 10
print("offset:", offset)
# todo 这使⽤加速度拖动,被极限识别,⽆法通过验证
# 使⽤偏移值计算移动操作
# track = _track(offset)
# 操作滑块按钮,模拟拖动滑块做验证登录
# self.operate_slider(track)
# todo 使⽤jquery⾃定义的移动轨迹拖动,通过验证
slider_bt = self.driver.find_element_by_xpath("//div[@class='geetest_slider_button']")
drag_and_drop(self.driver, offset + 40, slider_bt)
time.sleep(8)
当然还有输⼊密码过程中会检测⿏标的按下和弹起,但是⽤了好多模拟⽅法都⾏不通,这⾥强烈建议使⽤DD模拟⿏键的电信号来解决的,有需要⽤到可以参考我的上⼀篇⽂章,有DD详细的使⽤步骤。附链接如下:
感谢以上各位博主,让我解决了难题。借此整理出来给⼤家参考。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。