滑动验证码是近年来广泛应用于防止自动化登录的一种常见安全措施。本文将详细介绍如何使用 Python 和 Selenium 库破解滑动验证码。我们将逐步解析代码,帮助您理解每一部分的功能及实现方法。
环境准备
在开始之前,请确保您的计算机上已安装以下工具和库:
Python
Selenium 库
PIL (Pillow) 库
Chrome 浏览器及其驱动程序
安装必要的库
使用以下命令安装 Selenium 和 Pillow 库:
bash
pip install selenium pillow
下载 ChromeDriver
请从 ChromeDriver 官网 下载适用于您 Chrome 浏览器版本的驱动程序,并将其路径添加到系统环境变量中。
编写破解滑动验证码的代码
下面是完整的 Python 代码,接下来我们将逐段解析:
python
from selenium import webdriver # 用来驱动浏览器的
from selenium.webdriver import ActionChains # 破解滑动验证码的时候用的 可以拖动图片
import time
from PIL import Image
import random
option = webdriver.ChromeOptions()
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
初始化 WebDriver
首先,设置 Chrome 的启动选项并初始化 WebDriver。
python
option = webdriver.ChromeOptions()
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
获取网页截图
定义一个函数 get_snap 来截取整个页面并从中裁剪出验证码图片。
python
def get_snap(driver):
# selenium自带的截图网页全屏图片
driver.save_screenshot('snap.png')
img = driver.find_element_by_class_name('geetest_canvas_img')
left = img.location['x']
upper = img.location['y']
right = left + img.size['width']
lower = upper + img.size['height']
img_obj = Image.open('snap.png')
image = img_obj.crop((left, upper, right, lower))
return image
获取完整和有缺口的图片
分别定义两个函数 get_image1 和 get_image2 来获取完整图片和有缺口的图片。通过执行 JavaScript 代码来控制图片的显示和隐藏。
python
def get_image1(driver):
time.sleep(0.2)
js_code = '''
var x = document.getElementsByClassName('geetest_canvas_fullbg')[0].style.display="block";
console.log(x)
'''
time.sleep(1)
driver.execute_script(js_code)
img_obj = get_snap(driver)
return img_obj
def get_image2(driver):
time.sleep(0.2)
js_code = '''
var x = document.getElementsByClassName('geetest_canvas_fullbg')[0].style.display="none";
console.log(x)
'''
driver.execute_script(js_code)
time.sleep(1)
img_obj = get_snap(driver)
return img_obj
计算滑块需要移动的距离
通过比较两张图片的像素差异来确定滑块需要移动的距离。
python
def get_distance(image1, image2):
start = 60
color_num = 60
for x in range(start, image1.size[0]):
for y in range(image1.size[1]):
rgb1 = image1.load()[x, y]
rgb2 = image2.load()[x, y]
r = abs(rgb1[0] - rgb2[0])
g = abs(rgb1[1] - rgb2[1])
b = abs(rgb1[2] - rgb2[2])
if not (r < color_num and g < color_num and b < color_num):
return x - 7
生成滑动轨迹
根据滑块需要移动的距离生成一个滑动轨迹,使滑动过程看起来更像人为操作。
python
def get_stacks(distance):
distance += 20
v0 = 0
a_list = [3, 4, 5]
t = 0.2
s = 0
forward_stacks = []
mid = distance * 3 / 5
while s < distance:
if s < mid:
a = a_list[random.randint(0, 2)]
else:
a = -a_list[random.randint(0, 2)]
v = v0
stack = v * t + 0.5 * a * (t ** 2)
stack = round(stack)
s += stack
v0 = v + a * t
forward_stacks.append(stack)
back_stacks = [-1, -1, -2, -3, -2, -3, -2, -2, -3, -1]
return {'forward_stacks': forward_stacks, 'back_stacks': back_stacks}
主函数
主函数实现具体的操作流程,包括访问登录页面、输入用户名密码、获取验证码图片、计算滑动距离、模拟滑动等步骤。
python
def main():
try:
driver.get('https://passport.cnblogs.com/user/signin')
driver.implicitly_wait(5)
# 输入用户名与密码,点击登录
username = driver.find_element_by_id('LoginName')
password = driver.find_element_by_id('Password')
login_button = driver.find_element_by_class_name('ladda-label')
time.sleep(1)
username.send_keys('_tank_')
time.sleep(1)
password.send_keys('k46709394.')
time.sleep(1)
login_button.click()
# 点击滑动验证按钮,获取图片
geetest_button = driver.find_element_by_class_name('geetest_slider_button')
geetest_button.click()
time.sleep(0.2)
# 获取完整和有缺口的图片
image1 = get_image1(driver)
image2 = get_image2(driver)
# 计算滑动距离
distance = get_distance(image1, image2)
# 生成滑动轨迹
stacks = get_stacks(distance)
forward_stacks = stacks['forward_stacks']
back_stacks = stacks['back_stacks']
# 根据滑动轨迹进行滑动
slider_button = driver.find_element_by_class_name('geetest_slider_button')
time.sleep(0.2)
ActionChains(driver).click_and_hold(slider_button).perform()
time.sleep(0.2)
for forward_stack in forward_stacks:
ActionChains(driver).move_by_offset(xoffset=forward_stack, yoffset=0).perform()
time.sleep(0.1)
for back_stack in back_stacks:
ActionChains(driver).move_by_offset(xoffset=back_stack, yoffset=0).perform()
time.sleep(0.1)
time.sleep(0.2)
ActionChains(driver).move_by_offset(xoffset=5, yoffset=0).perform()
ActionChains(driver).move_by_offset(xoffset=-5, yoffset=0).perform()
ActionChains(driver).release().perform()
time.sleep(50)
finally:
driver.close()
if name == 'main':
main()
更多内容联系1436423940
版权归原作者 rrrrroottttttt 所有, 如有侵权,请联系我们删除。