python学习第七天

破解了极验的滑动验证

'''
博客园登录url:
    https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fwww.cnblogs.com%2F
1、输入用户名与密码,并点击登录
2、弹出滑动验证,获取有缺口与完整的图片
3、通过像素点进行对比,获取滑动距离位移
4、模拟人的行为轨迹
5、开始滑动

'''

from selenium import webdriver
from selenium.webdriver import ActionChains
import  time
from PIL import Image
import random
driver = webdriver.Chrome()

try:
    # 截取图片函数
    def cut_image(driver):
        # 获取整个页面图片,图片名字为snap
        driver.save_screenshot('snap.png')

        # 获取滑动小图片
        image = driver.find_element_by_class_name("geetest_canvas_img")
        print(image.location)
        print(image.size)

        # 获取小图片的左、上、右、下位置
        left = image.location['x']
        top = image.location['y']
        right = left + image.size['width']
        bottom = top + image.size['height']

        print(left, top, right, bottom)

        # 调用open方法打开全屏图片并赋值给image_obj对象
        image_obj = Image.open('snap.png')

        # 通过image_obj对象对小图片进行截图
        img = image_obj.crop((left, top, right, bottom))

        # 打开截取后的小图片
        # img.show()

        return img


    # 获取完整图片
    def get_image1(driver):

        time.sleep(2)
        # 修改document文档树,吧完整图片的display属性修改为block
        js_code = '''
            var x=document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block";

        '''
        # 执行js代码
        driver.execute_script(js_code)

        # 截取图片
        image = cut_image(driver)
        return image


    # 获取有缺口图片
    def get_image2(driver):
        time.sleep(5)
        # 修改document文档树,吧完整图片的display属性修改为block
        js_code = '''
            var x=document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="none";

        '''
        # 执行js代码
        driver.execute_script(js_code)

        # 截取图片
        image = cut_image(driver)
        return image


    # 获取滑块距离
    def get_distance(image1, image2):
        # 小滑块右侧距离
        start = 60

        # 像素差
        num = 60

        for x in range(start, image1.size[0]):
            for y in range(image1.size[1]):
                # 获取image1完整图片的每一个坐标的像素点
                rgb1 = image1.load()[x, y]  # (60,86,60)
                # 获取image2缺口图片的每一个坐标的像素点
                rgb2 = image2.load()[x, y]  # (60,86,60)
                print(rgb1, rgb2)

                # abs获取绝对值,像素点比较的值
                r = abs(rgb1[0] - rgb2[0])
                g = abs(rgb1[1] - rgb2[1])
                b = abs(rgb1[2] - rgb2[2])

                if not (r < num and g < num and b < num):
                    return x - 7


    # 模拟人的滑动轨迹
    def get_strck_move(distance):
        distance += 20
        # 初速度
        v0 = 0
        # 时间
        t = 0.2

        # 位置
        s = 0

        # 滑动轨迹列表
        move_list = []

        # 中间值,作为加减速度的位置
        mid = distance / 5 * 3

        # 加减速度列表
        v_list = [1, 2, 3, 4]

        # 循环位移
        while s < distance:
            if s < mid:
                # 随机获取一个加速度
                a = v_list[random.randint(0, len(v_list) - 1)]
            else:
                # 随机获取一个减速度
                a = -v_list[random.randint(0, len(v_list) - 1)]

            v = v0

            # 路程公式
            # s=v0*t+0.5*a*(t**2)

            s1 = v * t + 0.5 * a * (t ** 2)
            s1 = round(s1)  # 取整

            # 加速度公式
            # v=v0+a*t
            m_v = v + a * t

            # 把当前加/减速度赋值给初始速度,以便下一次计算
            v0 = m_v

            # 把位移添加到滑动列表中
            move_list.append(s1)

            # 修改滑动距离
            s += s1

        # 后退列表,自定义后退滑动轨迹,必须是负值
        back_list = [-1, -1, -2, -3, -2, -1, -1, -2, -3, -2, -1, -1]

        return {'move_list': move_list, 'back_list': back_list}


    def main():

        # 隐式等待,写在get请求之前###若为显示等待,写在get请求之后
        driver.implicitly_wait(10)

        driver.get('https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fwww.cnblogs.com%2F')

        # 1、输入用户名与密码,并点击登录
        user_input = driver.find_element_by_id('LoginName')
        user_input.send_keys('Hi!Superman')
        time.sleep(0.2)

        pwd_input = driver.find_element_by_id('Password')
        pwd_input.send_keys('********')
        time.sleep(2)

        login_submit = driver.find_element_by_id('submitBtn')
        login_submit.click()

        # 2、获取完整图片
        image1 = get_image1(driver)

        # 3、获取有缺口的图片
        image2 = get_image2(driver)
        time.sleep(10)

        # 对比两张图片,获取滑动距离
        distance = get_distance(image1, image2)
        print(distance)

        # 模拟人的滑动轨迹
        move_dict = get_strck_move(distance)

        # 获取前进滑动轨迹
        move_list = move_dict['move_list']
        # 获取后退滑动轨迹
        back_list = move_dict['back_list']

        # 6、开始滑动
        move_tag = driver.find_element_by_class_name('geetest_slider_button')
        # 点击按住滑动按钮
        ActionChains(driver).click_and_hold(move_tag).perform()

        # 向前滑动
        for move in move_list:
            ActionChains(driver).move_by_offset(xoffset=move, yoffset=0).perform()
            time.sleep(0.2)

        # 向后滑动
        for back in back_list:
            ActionChains(driver).move_by_offset(xoffset=back, yoffset=0).perform()
            time.sleep(0.2)

        # 制作微妙晃动
        ActionChains(driver).move_by_offset(xoffset=3, yoffset=0).perform()
        ActionChains(driver).move_by_offset(xoffset=-3, yoffset=0).perform()
        time.sleep(0.2)

        # 释放滑动按钮
        ActionChains(driver).release().perform()


finally:
    driver.close()


if __name__ == '__main__':
    main()

snap.png图如下:

通过今天的学习,学会了通过selenium破解极验验证码,实现博客园的自动登录,特别新奇有趣。

原文地址:https://www.cnblogs.com/zmmm/p/11060707.html