selenium之滑块验证码破解代码详解

Posted 千叶千影

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了selenium之滑块验证码破解代码详解相关的知识,希望对你有一定的参考价值。

PS:浏览器和电脑的缩放应该调为100%(Windows默认为125%),否则可能会导致获取局部图片时出现误差!
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from PIL import Image
import time


def get_snapshot():
    "获取整个页面的快照,并返回图片对象"
    driver.save_screenshot(\'snapshot.png\')
    pic_obj = Image.open(\'snapshot.png\')
    return pic_obj

def get_image():
    # 获取滑块验证码图片所在div的元素对象
    element = driver.find_element_by_xpath(\'//div[@class="geetest_slicebg geetest_absolute"]\')
    # 计算滑块验证码部分截图的坐标
    left = element.location[\'x\']
    top = element.location[\'y\']
    right = left + element.size[\'width\']
    bottom = top + element.size[\'height\']
    # 先获取整个界面截图的对象
    pic_obj = get_snapshot()
    # 获取滑块验证码部分截图对象
    part_pic_obj = pic_obj.crop((left, top, right, bottom))
    return part_pic_obj

def get_distance(image1, image2):
    \'\'\'
    拿到滑动验证码需要移动的距离
    :param image1:没有缺口的图片对象
    :param image2:带缺口的图片对象
    :return:需要移动的距离
    \'\'\'
    # 从图像的左侧60像素开始匹配,把填充的那部分去掉,不比较,避免干扰。
    left = 60
    for i in range(left, image1.size[0]):  # 图像的宽
        for j in range(image1.size[1]):  # 图像的高
            rgb1 = image1.load()[i, j]
            rgb2 = image2.load()[i, j]
            res1 = abs(rgb1[0] - rgb2[0])
            res2 = abs(rgb1[1] - rgb2[1])
            res3 = abs(rgb1[2] - rgb2[2])
            # 自定义容差为30,则定义为缺口
            if res1 >= 30 and res2 >= 30 and res3 >= 30:
                return i - 7  # 误差大概是7
    pass

def get_tracks(distance):
    \'\'\'
    拿到移动轨迹,模仿人的滑动行为,先匀加速后匀减速
    匀变速运动基本公式:
    ①v=v0+at
    ②s=v0t+½at²
    ③v²-v0²=2as
    :param distance: 需要移动的距离
    :return: 存放每0.2秒移动的距离
    \'\'\'
    # 初速度
    v = 0
    # 单位时间为0.2s来统计轨迹,轨迹即0.2内的位移
    t = 0.2
    # 位移/轨迹列表,列表内的一个元素代表0.2s的位移
    tracks = []
    # 当前的位移
    current = 0
    # 到达mid值开始减速
    mid = distance * 4 / 5
    while current < distance:
        if current < mid:
            # 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
            a = 2
        else:
            a = -3
        # 初速度
        v0 = v
        # 0.2秒时间内的位移
        s = v0 * t + 0.5 * a * (t ** 2)
        # 当前的位置
        current += s
        # 添加到轨迹列表
        tracks.append(round(s))
        # 速度已经达到v,该速度作为下次的初速度
        v = v0 + a * t
    return tracks

if __name__ == \'__main__\':
    try:
        driver = webdriver.Chrome()
        driver.get(\'https://account.ch.com/NonRegistrations-Regist\')
        driver.maximize_window()
        driver.find_element_by_name(\'phoneNumberInput\').send_keys(\'15216122411\')


        # 单击,让滑块验证码的图片显示,这里有4种方法,有些可能会点击无效
        getDynamicPwd = driver.find_element_by_xpath(\'//a[@id="getDynamicPwd"]\')
        ActionChains(driver).move_to_element(getDynamicPwd).move_by_offset(5,0).click().perform()
        # driver.find_element_by_xpath(\'//a[@id="getDynamicPwd"]\').click()
        # driver.execute_script(\'document.getElementById("getDynamicPwd").click()\')
        # driver.find_element_by_id(\'getDynamicPwd\').click()

        time.sleep(2)  # 沉睡两秒,加载滑块验证码

        # 获取有缺口的滑块验证局部截图
        image1 = get_image()
        # image1.save(\'imag1.png\') # 获取局部截图

        # 获取没有缺口的图片
        driver.execute_script(\'document.getElementsByClassName("geetest_canvas_fullbg")[0].style="display:block"\')
        image2 = get_image()
        # image2.save(\'imag2.png\') # 获取局部截图

        distance = get_distance(image1, image2)

        # 获取滑块
        huakuai = driver.find_element_by_xpath(\'//div[@class="geetest_slider_button"]\')

        # 拉动滑块开始执行
        ActionChains(driver).click_and_hold(on_element=huakuai).perform()
        ActionChains(driver).move_by_offset(xoffset=distance * 0.5, yoffset=0).perform() #闪现50%

        # 模拟人的行为习惯(先匀加速拖动后匀减速拖动),把需要拖动的总距离分成一段一段小的轨迹
        tracks = get_tracks(distance * 0.5) # 剩下的50%在模拟移动
        for x in tracks:
            ActionChains(driver).move_by_offset(xoffset=x, yoffset=0).perform()
        else:
            ActionChains(driver).move_by_offset(xoffset=3, yoffset=0).perform()  # 先移过一点
            ActionChains(driver).move_by_offset(xoffset=-3, yoffset=0).perform()  # 再退回来,看上去更像人为

        # 0.5s释放鼠标
        time.sleep(0.5)
        ActionChains(driver).release().perform()

    except Exception as error:
        print(error)
        driver.close()

 



以上是关于selenium之滑块验证码破解代码详解的主要内容,如果未能解决你的问题,请参考以下文章

登录校验之滑块验证码完整实现(vue + springboot)

验证码之滑块验证码

python+Selenium之自动滑块破解滑块验证码

Selenium实战滑动验证码破解JAVA爬虫

用Python+Selenium破解春秋航空网滑块验证码,信息安全之路

Selenium实战滑动验证码破解JAVA爬虫