爬虫之滑动验证破解

滑动验证码

编程思路

  1. 封装一个函数进行登录
    • 创建一个driver对象
    • 找到输入框和密码框,将用户名和密码输入
    • 找到登录按钮
    • 破解滑动验证码(封装函数)
    • 关闭浏览器对象
  2. 封装一个函数,用于破解滑动验证码
    • 计算滑动距离
      • 截取带缺口的图(封装函数)
      • 用js语句去掉缺口
      • 截取不带缺口的图
      • 把去掉的缺口补回来
      • 根据两张图片的缺口处的像素差异,来求出存在差异的第一个像素的x轴坐标,即为滑动距离(封装函数)
    • 模拟人类的动作来滑动
      • 按住滑块按钮
      • 按照距离来拖动(封装函数)
      • 前向移动
      • 松开滑块按钮
  3. 定义一个函数用于截图
    • 截取整个浏览器的图
    • 加载图片
    • 从整个浏览器区域中截取出验证码区域
      • 提取验证码区域的位置(距x轴和距y轴的距离)
      • 提取验证码区域的大小(宽和高)
    • 根据位置和大小来计算验证码区域的截取范围
    • 根据截取范围将验证码区域的图片截取出来
    • 返回截取的图片
  4. 封装一个函数,用于根据两张图片的像素差异来计算滑动距离
    • 获取每一个像素点的rgb值
    • 计算两个图片的rgb差异
    • 判断差异是否大于经验值,大于则返回该像素点的x坐标,即为移动距离
  5. 封装一个函数模拟匀加速运动的轨迹
    • 定义滑动距离拖动的时候多拖出去20(完全模拟人操作)
    • 定义一个中间位置,前面加速,后面减速
    • 定义一个变量用于存放每一段的轨迹
    • 将每一段的位移s加入轨迹中
    • 返回一个字典,存放前向和反向轨迹

代码实现

#导包
from selenium import webdriver
from time import sleep
from PIL import Image
from selenium.webdriver import ActionChains

# 定义一个函数用于截图
def shot_img(driver):
    sleep(2)
    # 截取整个浏览器的图
    driver.save_screenshot("./page.png")
    # 加载图片
    img = Image.open("./page.png")
    # img.show()
    # 从整个浏览器区域中截取出验证码区域
    loc = driver.find_element_by_class_name("geetest_slicebg").location # 提取验证码区域的位置(距x轴和距y轴的距离)
    size = driver.find_element_by_class_name("geetest_slicebg").size # 提取验证码区域的大小(宽和高)
    # 根据loc和size来计算验证码区域的截取范围
    top = loc["y"]
    bottom = loc["y"] + size["height"]
    left = loc["x"]
    right = loc["x"] + size["width"]
    # 根据截取范围将验证码区域的图片截取出来(后面的系数根据自己电脑配置自行调节)
    code_img = img.crop((left*2,top/2,right*2,bottom*1.2))
    # code_img.show()
    return code_img

# 封装一个函数,用于根据两张图片的像素差异来计算滑动距离
def get_distance(img1,img2):
    for i in range(50,img1.size[0]):
        for j in range(0,img1.size[1]):
            # 获取每一个像素点的rgb值
            rgb1 = img1.load()[i,j]
            rgb2 = img2.load()[i,j]
            # 计算两个图片的rgb差异
            r = abs(rgb1[0] - rgb2[0])
            g = abs(rgb1[1] - rgb2[1])
            b = abs(rgb1[2] - rgb2[2])
            # 判断差异
            if r>60 and g>60 and b>60:
                return i/2 - 6


# 封装一个函数,用于提供模拟匀加速运动的轨迹
def tracks(distance):
    # 拖动的时候多拖出去20
    distance += 20
    v = 0
    t = 0.2
    # 定义一个中间位置,以前匀加速,以后匀减速
    mid = distance*3/5
    # 定义一个变量用于记录当前位置
    current = 0
    # 定义一个变量用于存放每一段的轨迹
    farwords = []
    while current < distance:
        if current < mid:
            a = 2
        else:
            a = -3
        s = v*t + 1/2*a*t**2
        v = a*t + v
        current += s
        # 将每一段的位移s加入轨迹中
        farwords.append(round(s))
    # 返回一个字典,里面存放前向和反向轨迹
    return {"farwords":farwords,"backs":[-3,-3,-3,-2,-2,2,-2,-2,-3,-1,-1]}



# 封装一个函数,用于破解滑动验证码
def crack_code(driver):
    # 1、计算滑动距离
    # 1)截取带缺口的图
    img1 = shot_img(driver)
    # 2)去掉缺口
    # 用js语句来去掉缺口
    js = "document.querySelector('.geetest_canvas_slice').style.zIndex=10;document.querySelector('.geetest_canvas_slice').style.display='block';document.querySelector('.geetest_canvas_fullbg').style.display='block';"
    driver.execute_script(js)

    # 3)截取不带缺口的图
    img2 = shot_img(driver)

    # 4)把去掉的缺口补回来
    js = "document.querySelector('.geetest_canvas_slice').style.zIndex=10;document.querySelector('.geetest_canvas_slice').style.display='block';document.querySelector('.geetest_canvas_fullbg').style.display='none';"
    driver.execute_script(js)

    # 5) 根据两张图片的缺口处的像素差异,来求出存在差异的第一个像素的x轴坐标,即为滑动距离
    distance = get_distance(img1,img2)
    print(distance)
    # 2、模拟人类的动作来滑动
    btn = driver.find_element_by_class_name("geetest_slider_button")
    # 1)按住滑块按钮
    ActionChains(driver).click_and_hold(btn).perform()
    sleep(0.5)
    # 2)按照距离来拖动
    # ActionChains(driver).move_by_offset(xoffset=distance,yoffset=0).perform() # 拖动的时候要尽量慢一些更像人类动作
    # 获取轨迹
    track_dict = tracks(distance)
    # 前向移动
    for track in track_dict["farwords"]:
        ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()
    sleep(0.5)
    # 反向移动
    for track in track_dict["backs"]:
        ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()
    sleep(0.5)
    # 3)松开滑块按钮
    ActionChains(driver).release().perform()




# 封装一个函数用于登录
def login_blogs(url,name,password):
    # 创建一个driver对象
    driver = webdriver.Chrome()
    try:
        driver.get(url)
        sleep(1)
        # 找到输入框和密码框,将用户名和密码输入
        driver.find_element_by_id("LoginName").send_keys(name)
        driver.find_element_by_id("Password").send_keys(password)
        # 找到登录按钮
        driver.find_element_by_id("submitBtn").click()
        sleep(1)
        # 破解滑动验证码
        crack_code(driver)
        sleep(5)
    finally:
        driver.close()


if __name__ == '__main__':
    url = "https://account.cnblogs.com/signin"
    login_blogs(url,"qwer","1234")

你可能感兴趣的:(爬虫与数据分析)