滑块验证码是生活中非常常见的一种验证方式,在爬虫过程中如果遇到改怎么解决呢?当然我们可以手动划过去再执行下面的代码,但是这样不符合我们效率至上的原则。
破解思路:
使用 selenium 模拟人为的操作,将滑块移动到指定的位置,然后松开鼠标
核心思路:
计算出移动的距离
怎么计算:
找到无缺口的图片,对比两张图片,通过求出图片中每一个点的颜色的 RGB 值,找出缺口位置
大致过程:
import selenium from webdriver
driver = webdriver.Chrome(插件位置)
# 最大化窗口,方便定位图片
driver.maxmize_window()
# 截图,获取有缺口的图片
driver.save_scerrnshot('quekou.png')
# 通过获取图片元素来准准确定位图片
ele = driver.find_element(By.XPATH,'xpath路径')
# 根据图片元素位置进行局部截图
# 目的:为了方便对比RGB值,需要将最左边的拼图块截掉,以免对后面的对比造成干扰
left = ele.location['x']
right = ele.location['x'] + ele.size['width']
top = ele.location['y']
bottom = ele.location['y'] + ele.size['height']
# 打开之前截取的整页图片
# 这里用到PIL模块
from PIL import Image
im = Image.open('quanbu.png')
im = im.crop((left * 2 + 110, top * 2 + 10, right * 2, bottom * 2))
# 注意win设备不需要*2
# 保存图片
im.save('wuque_jubu.png')
找到完整图片:
这样我们就获得了带缺口的局部截图,接下来就是要找到完整的图片,一般两个标签会离的很近
# 找出无缺口的图片
# 执行js
driver.execute_script('document.getElementsByClassName("这里输入class的值")[0].style="display:block"')
# 截图
driver.save_screenshot('wuque.png')
im = Image.open('wuque.png')
im = im.crop((left * 2 + 110, top * 2 + 10, right * 2, bottom * 2))
# 同理,Mac*2,win不需要
im.save('wuque_jubu.png')
这样我们就获得了有缺口和没有缺口的两证图片,并且两张图片大小完全一致,方便我们后面的比较
定义计算距离的函数及判断相似的函数
# 定义计算距离的函数
def get_difference(image1,image2):
for i in range(image1.width):
for j in range(image1.height):
if is_similar(image1,image2,i,j):
return i
# 定义判断相似的函数
def is_similar(image1,image2,x,y):
# 计算每一个点在对应图片中的rgb值,判断是否缺口
# 计算RGB值的方法
pixel1 = image1.getpixel((x,y))
pixel2 = image2.getpixel((x,y))
# 找出缺口
# 需要设置一个容差范围,如果超出这个范围为缺口,否则不是缺口
if abs(pixel1[0] - pixel2[0]) > 30 and abs(pixel1[1] - pixel2[1]) > 30 and abs(pixel1[2] - pixel2[2]) > 30:
return True
return False
接下来就调用定义好的函数来计算移动距离
计算移动距离
im1 = Image.open('wuque_jubu.png')
im2 = Image.open('quekou_jubu.png')
distance = get_difference(im1, im2)
然后找到滑块按钮,开始移动滑块就好
开始移动滑块
huakuai = driver.find_element(By.XPATH,'xpath路径')
# 按住滑块并保持不动
# 这里需要导入selenium的动作链
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).click_and_hold(on_element=huakuai).perform()
# 滑动滑块
ActionChains(driver).move_by_offset(xoffset=(distance + 55) * 0.6, yoffset=0).perform()
# 松开鼠标
ActionChains(driver).release().perform()
但是,程序移动滑块的速度是非常快的,直接就闪现过去了,一般是成功不了的,正常网页都会有判断,速度过快时无法通过的,这里就需要用到物理的加速运动了,我们让程序来做匀加匀减速运动,本人身为一个物理黑洞,只能拿大佬定义好的来用了…….
定义计算运动轨迹的函数
def get_distance(distance):
"""
x = v0*t + 1/2 * a * t ** 2
v = v0 + a * t
"""
# 定义单位时间
t = 0.3
# 定义初速度
v = 0
# 定义存放运动轨迹的容器
distance_list = []
# 定义匀加速和匀减速的分界线
mid = distance * 0.8
# 定义当前位移
current = 0
while current < distance:
if current < mid:
# 匀加速运动
a = 2
else:
# 匀减速运动
a = -3
# 计算位移
x = v * t + 1 / 2 * a * t ** 2
current += x
# 计算末速度
v = v + a * t
distance_list.append(round(x))
return distance_list
然后我们需要在松开鼠标之前加入模拟先加速后减速的运动
# 利用物理加速度,模拟出先加速后减速的运动
distance_list = get_distance((distance + 55) * 0.4)
for i in distance_list:
ActionChains(driver).move_by_offset(xoffset=i, yoffset=0).perform()
总结:
这就是本人总结的破解滑块验证码的具体思路了,但是在很多网站都会针对进行检测,成功率较低,需要不断的实验来调整程序滑动的运动轨迹来减少被检测的几率