zoukankan      html  css  js  c++  java
  • web 自动化 图片 滑动验证码如何解决

    qq空间滑动验证图片:

      

    本模块专门用来处理滑动验证码的问题

    from selenium.webdriver import ActionChains
    import random, time, os
    import cv2
    from PIL import Image as Im
    import numpy as np
    import requests
    
    
    class SlideVerificationCode():
        """滑动验证码破解"""
    
        def __init__(self, count=5, save_image=False):
            """
            :param count: 验证重试的次数,默认为5次
            :param save_image: 是否保存验证过程中的图片,默认不保存
            """
            self.count = count
            self.save_image = save_image
    
        def slide_verification(self, driver, slide_element, distance):
            """
            :param driver: driver对象
            :type driver:webdriver.Chrome
            :param slide_element: 滑块的元组
            :type slider_ele: WebElement
            :param distance:  滑动的距离
            :type: int
            :return:
            """
            start_url = driver.current_url
            print("需要滑动的距离为:", distance)
            locus = self.get_slide_locus(distance)
            print("生成的滑动轨迹为:{},轨迹的距离之和为{}".format(locus, distance))
            ActionChains(driver).click_and_hold(slide_element).perform()
            time.sleep(0.5)
            for loc in locus:
                time.sleep(0.01)
                ActionChains(driver).move_by_offset(loc, random.randint(-5, 5)).perform()
                ActionChains(driver).context_click(slide_element)
            ActionChains(driver).release(on_element=slide_element).perform()
            time.sleep(2)
            end_url = driver.current_url
            if start_url == end_url and self.count > 0:
                print("第{}次验证失败,开启重试".format(6 - self.count))
                self.count -= 1
                self.slide_verification(driver, slide_element, distance)
    
        def onload_save_img(self, url, filename="image.png"):
            """
            下载图片保存
            :param url:图片地址
            :param filename: 保存的图片名
            :return:
            """
            try:
                response = requests.get(url=url)
            except(requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError)as e:
                print("图片下载失败")
                raise e
            else:
                with open(filename, "wb") as f:
                    f.write(response.content)
    
        def get_element_slide_distance(self, slider_ele, background_ele, correct=0):
            """
            根据传入滑块,和背景的节点,计算滑块的距离
    
            该方法只能计算 滑块和背景图都是一张完整图片的场景,
            如果是通过多张小图拼接起来的背景图,该方法不适用,后续会补充一个专门针对处理该场景的方法
            :param slider_ele: 滑块图片的节点
            :type slider_ele: WebElement
            :param background_ele: 背景图的节点
            :type background_ele:WebElement
            :param correct:滑块缺口截图的修正值,默认为0,调试截图是否正确的情况下才会用
            :type: int
            :return: 背景图缺口位置的X轴坐标位置(缺口图片左边界位置)
            """
            slider_url = slider_ele.get_attribute("src")
            background_url = background_ele.get_attribute("src")
            slider = "slider.jpg"
            background = "background.jpg"
            self.onload_save_img(slider_url, slider)
            self.onload_save_img(background_url, background)
            slider_pic = cv2.imread(slider, 0)
            background_pic = cv2.imread(background, 0)
            width, height = slider_pic.shape[::-1]
            slider01 = "slider01.jpg"
            background_01 = "background01.jpg"
            cv2.imwrite(background_01, background_pic)
            cv2.imwrite(slider01, slider_pic)
            slider_pic = cv2.imread(slider01)
            slider_pic = cv2.cvtColor(slider_pic, cv2.COLOR_BGR2GRAY)
            slider_pic = abs(255 - slider_pic)
            cv2.imwrite(slider01, slider_pic)
            slider_pic = cv2.imread(slider01)
            background_pic = cv2.imread(background_01)
            result = cv2.matchTemplate(slider_pic, background_pic, cv2.TM_CCOEFF_NORMED)
            top, left = np.unravel_index(result.argmax(), result.shape)
            print("当前滑块的缺口位置:", (left, top, left + width, top + height))
            if self.save_image:
                loc = (left + correct, top + correct, left + width - correct, top + height - correct)
                self.image_crop(background, loc)
            else:
                os.remove(slider01)
                os.remove(background_01)
                os.remove(slider)
                os.remove(background)
            return left
    
        def get_image_slide_dictance(self, slider_image, background_image, correct=0):
            """
            根据传入滑块,和背景的图片,计算滑块的距离
    
            该方法只能计算 滑块和背景图都是一张完整图片的场景,
            如果是通过多张小图拼接起来的背景图,该方法不适用,后续会补充一个专门针对处理该场景的方法
            :param slider_iamge: 滑块图的图片
            :type slider_image: str
            :param background_image: 背景图的图片
            :type background_image: str
            :param correct:滑块缺口截图的修正值,默认为0,调试截图是否正确的情况下才会用
            :type: int
            :return: 背景图缺口位置的X轴坐标位置(缺口图片左边界位置)
            """
            slider_pic = cv2.imread(slider_image, 0)
            background_pic = cv2.imread(background_image, 0)
            width, height = slider_pic.shape[::-1]
            slider01 = "slider01.jpg"
            background_01 = "background01.jpg"
            cv2.imwrite(background_01, background_pic)
            cv2.imwrite(slider01, slider_pic)
            slider_pic = cv2.imread(slider01)
            slider_pic = cv2.cvtColor(slider_pic, cv2.COLOR_BGR2GRAY)
            slider_pic = abs(255 - slider_pic)
            cv2.imwrite(slider01, slider_pic)
            slider_pic = cv2.imread(slider01)
            background_pic = cv2.imread(background_01)
            result = cv2.matchTemplate(slider_pic, background_pic, cv2.TM_CCOEFF_NORMED)
            top, left = np.unravel_index(result.argmax(), result.shape)
            print("当前滑块的缺口位置:", (left, top, left + width, top + height))
            if self.save_image:
                loc = (left + correct, top + correct, left + width - correct, top + height - correct)
                self.image_crop(background_image, loc)
            else:
                os.remove(slider01)
                os.remove(background_01)
            return left
    
        @classmethod
        def get_slide_locus(self, distance):
            """
            根据移动坐标位置构造移动轨迹,前期移动慢,中期块,后期慢
            :param distance:移动距离
            :type:int
            :return:移动轨迹
            :rtype:list
            """
            remaining_dist = distance
            locus = []
            while remaining_dist > 0:
                ratio = remaining_dist / distance
                if ratio < 0.2:
                    span = random.randint(2, 8)
                elif ratio > 0.8:
                    span = random.randint(5, 8)
                else:
                    span = random.randint(10, 16)
                locus.append(span)
                remaining_dist -= span
            return locus
    
        def image_crop(self, image, location, new_name="new_image.png"):
            """
            对图片的指定位置进行截图
            :param image: 被截取图片的坐标位置
            :param location:需要截图的坐标位置:(left,top,right,button)
            :type location: tuple
            :return:
            """
            image = Im.open(image)
            imagecrop = image.crop(location)
            imagecrop.save(new_name)

    qq空间登录滑动图片验证

    import time
    from selenium import webdriver
    from web_项目前期.AlideVerification.slideVerfication import SlideVerificationCode
    
    # 1、创建一个driver对象,访问qq登录页面
    browser = webdriver.Chrome()
    browser.get("https://qzone.qq.com/")
    
    # 2、输入账号密码
    
    # 2.0 点击切换到登录的iframe
    browser.switch_to.frame('login_frame')
    
    # 2.1 点击账号密码登录
    browser.find_element_by_id('switcher_plogin').click()
    
    # 2.2定位账号输入框,输入账号
    browser.find_element_by_id("u").send_keys("1938091409")
    
    # 2.3定位密码输入输入密码
    browser.find_element_by_id("p").send_keys("aini2141339856.0")
    
    # 3、点击登录
    browser.find_element_by_id('login_button').click()
    time.sleep(3)
    
    # 4、模拟滑动验证
    # 4.1切换到滑动验证码的iframe中
    tcaptcha = browser.find_element_by_id("tcaptcha_iframe")
    browser.switch_to.frame(tcaptcha)
    
    # 4.2选择拖动滑块的节点
    slide_element = browser.find_element_by_id('tcaptcha_drag_thumb')
    
    #  模拟拖到滑块进行识别
    sc = SlideVerificationCode(save_image=True)
    
    # 获取滑块图片的节点id="slideBlock"
    slideBlock_ele = browser.find_element_by_id('slideBlock')
    # 获取背景图片节点id="slideBg"
    slideBg = browser.find_element_by_id('slideBg')
    
    # 4.3计算滑动距离,电脑缩放比例需要为100% 才可确保减去的正确
    distance = sc.get_element_slide_distance(slideBlock_ele, slideBg)
    print("滑动的距离为:", distance)
    # 滑动距离误差校正,按照比例来进行计算,然后减去 第一部分距离
    distance = distance*(280 / 680) - 31
    
    print("校验后的滑动距离", distance)
    
    # 4.4、进行滑动
    sc.slide_verification(browser, slide_element, distance=distance)
    
    time.sleep(2)
    browser.close()

    *******请大家尊重原创,如要转载,请注明出处:转载自:https://www.cnblogs.com/shouhu/,谢谢!!******* 

  • 相关阅读:
    面向对象 (11)求交并集 判断字符形式
    软件工程 课程总结
    面向对象 (10)正则判邮箱
    面向对象 (9)计算时间差 找随机数范围内规律
    面向对象 (8)字符串出现字符个数统计 字母组成回文串判定
    面向对象 (7)中介买房 平均数异常处理
    面向对象 (6)买房付首款
    第16周作业
    第15周作业
    迟到的第14周作业
  • 原文地址:https://www.cnblogs.com/shouhu/p/12761937.html
Copyright © 2011-2022 走看看