破解bilibili滑动验证码,pyautogui实现

背景:

本文主要以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、截取带滑块的图片

破解bilibili滑动验证码,pyautogui实现_第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、截取不带滑块的原图

破解bilibili滑动验证码,pyautogui实现_第2张图片

screen_shot("end")

3、对比两张图片的rgb,计算出滑动距离

破解bilibili滑动验证码,pyautogui实现_第3张图片

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

 

你可能感兴趣的:(爬虫)