本文主要以pyautogui库模拟人操作,替代了selenium.webdriver.Keys,由于pyautogui封装了缓动/渐变函数,所以省去了计算加速度等数学物理公式,使用少量代码便可完成破解工作。
本文思路来源自https://www.cnblogs.com/98WDJ/p/11050559.html
整体解决步骤:
1、截取带滑块的验证图片
2、截取未带滑块的完整图片
3、对比两张图片的rgb,计算出滑动距离
4、pyautogui模拟人滑动相应距离
文章末尾有完整代码
首先声明一个全局变量,获取浏览器的工具栏高度
browser_tool_height=driver.execute_script("return window.outerHeight-window.innerHeight") #工具栏高度
实现一个截图函数,截取图片的方法使用pyautogui的screenshot函数
def screen_shot(pic_name):
vpic=driver.find_element_by_class_name("geetest_canvas_img")
vpic_pos_x=vpic.location["x"] #浏览器中图片的起点x
vpic_pos_y=vpic.location["y"] #浏览器中图片的起点y
vpic_width=vpic.size["width"] #图片宽
vpic_height=vpic.size["height"] #图片高
# pyautogui.moveTo(vpic_pos_x, vpic_pos_y + browser_tool_height,duration=1) #这两句可以方便看到自己截取图片的位置,可注释掉
# pyautogui.moveTo(vpic_pos_x+vpic_width, vpic_pos_y + browser_tool_height+vpic_height,duration=1)
pyautogui.screenshot(pic_name+'.png', region=(vpic_pos_x, vpic_pos_y + browser_tool_height, vpic_width, vpic_height)) #截屏函数。region为一个元祖,内容为初始x,y和偏移坐标
1、截取带滑块的图片
screen_shot("before")
改变js,显示原图
driver.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];"
"x.style.display='block';"
"x.style.opacity=1"
)
2、截取不带滑块的原图
screen_shot("end")
3、对比两张图片的rgb,计算出滑动距离
before=Image.open('before.png') #加载带滑块的图片
end=Image.open('end.png') #加载不带滑块的图片
def get_distance(img1,img2):
start_x=54
gap=5
threhold=60 #阈值
for x in range(start_x,img1.size[0]):
for y in range(img1.size[1]):
rgb1=img1.load()[x,y]
rgb2=img2.load()[x,y]
res1=abs(rgb1[0]-rgb2[0])
res2=abs(rgb1[1]-rgb2[1])
res3=abs(rgb1[2]-rgb2[2])
if not (res1
4、pyautogui模拟人滑动相应距离
drag_button=driver.find_element_by_class_name("geetest_slider_button")
drag_button_x=drag_button.location["x"]
drag_button_y=drag_button.location["y"]+browser_tool_height
pyautogui.moveTo(drag_button_x+50,drag_button_y+50) #鼠标移动到滑动按钮
'''
模拟人先滑过缺口,再滑回来的动作
tween=pyautogui.easeInQuad 开始很慢,不断加速
tween=pyautogui.easeOutQuad 开始很快,不断减速
'''
pyautogui.mouseDown()
pyautogui.moveTo(drag_button_x+50+slice_distance+50,drag_button_y+50, duration=1, tween=pyautogui.easeInQuad)
pyautogui.moveTo(drag_button_x+50+slice_distance,drag_button_y+50, duration=1, tween=pyautogui.easeOutQuad)
pyautogui.mouseUp()
from selenium import webdriver
import time
import pyautogui
from PIL import Image
driver=webdriver.Chrome()
driver.get("https://passport.bilibili.com/login")
time.sleep(1)
driver.find_element_by_id("login-username").send_keys("111")
driver.find_element_by_id("login-passwd").send_keys("222")
time.sleep(1)
driver.find_element_by_class_name("btn-login").click()
time.sleep(1)
browser_tool_height=driver.execute_script("return window.outerHeight-window.innerHeight") #工具栏高度
def screen_shot(pic_name):
vpic=driver.find_element_by_class_name("geetest_canvas_img")
vpic_pos_x=vpic.location["x"] #浏览器中图片的起点x
vpic_pos_y=vpic.location["y"] #浏览器中图片的起点y
vpic_width=vpic.size["width"] #图片宽
vpic_height=vpic.size["height"] #图片高
# pyautogui.moveTo(vpic_pos_x, vpic_pos_y + browser_tool_height,duration=1) #这两句可以方便看到自己截取图片的位置,可注释掉
# pyautogui.moveTo(vpic_pos_x+vpic_width, vpic_pos_y + browser_tool_height+vpic_height,duration=1)
pyautogui.screenshot(pic_name+'.png', region=(vpic_pos_x, vpic_pos_y + browser_tool_height, vpic_width, vpic_height)) #截屏函数。region为一个元祖,内容为初始x,y和偏移坐标
screen_shot("before")
driver.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];"
"x.style.display='block';"
"x.style.opacity=1"
)
screen_shot("end")
before=Image.open('before.png') #加载带滑块的图片
end=Image.open('end.png') #加载不带滑块的图片
def get_distance(img1,img2):
start_x=54
gap=5
threhold=60 #阈值
for x in range(start_x,img1.size[0]):
for y in range(img1.size[1]):
rgb1=img1.load()[x,y]
rgb2=img2.load()[x,y]
res1=abs(rgb1[0]-rgb2[0])
res2=abs(rgb1[1]-rgb2[1])
res3=abs(rgb1[2]-rgb2[2])
if not (res1