zoukankan      html  css  js  c++  java
  • 滑动验证码(无原图片处理)

     
     
    from _pytest.mark import param
    from seleniumbase.config import settings
    from urllib3 import request
    from pageobject.basepage import BasePage
    import allure
    from PIL import Image
    from io import BytesIO
    import re
    import random
    import base64
    from tools import common
    from selenium.webdriver import ActionChains
    import cv2
    from pageobject.page.navigation_bar import Navigation
    import requests
    import settings
    import json
    import time


    class Login(BasePage):
        url = '/login'
        usernameInput = "//input[@name='username']"
        passwordInput = "//input[@name='password']"
        loginButton = "//input[@value='登录']/.."
        slider = "//div[@id='slider']"
        smallImageblocks = "//img[@class='smallImageblocks']"
        bgImage = "//img[@class='bgImage']"

        def open(self):
            '''
            打开账号密码登录页
            '''
            self._open(self.url)

        def type_name(self, value):
            '''
            输入用户名
            '''
            self.input(self.usernameInput, value)

        def type_pw(self, value):
            '''
            输入密码
            '''
            self.input(self.passwordInput, value)

        def click_login(self):
            '''
            点击登录
            '''
            self.click(self.loginButton)

        def hover_slider(self):
            '''
            停留在滑块上,并设置图片可见
            '''
            self.hover_on_element(self.slider)
            self.set_attribute(self.bgImage+"/..", 'class', 'slidePanel')

        def set_slider_success(self):
            '''
            设置图片验证成功
            '''
            self.set_attribute(self.slider+"/../..", 'class',
                               "sliderContainer sliderContainer_success")


    class VerificationCode(Login):
        def get_img(self, loc):
            '''
            获取图片
            :param driver:
            :param div_class:
            :param num:
            :return:
            '''
            imge_url = ''
            location = {}
            imge_url = self.get_attribute(loc, 'src')
            try:
                location['x'] = re.findall(
                    r'padding-top: (.*?)px;', self.get_attribute(loc, 'style'))[0]
            except Exception:
                location['x'] = 0
            try:
                location['y'] = re.findall(
                    r'padding-top: (.*?)px; left: (.*?)px;', self.get_attribute(loc, 'style'))[1]
            except Exception:
                location['y'] = 0
            b64_data = imge_url.split(';base64,')[1]
            data = base64.b64decode(b64_data)
            img_content = BytesIO(data)
            image = Image.open(img_content)
            image = image.convert('RGB')
            name = f'{common.dir}/file/temporary/{str(random.randint(1, 100))}.jpg'
            image.save(name)
            return name

        def get_track(self, x):
            '''
            滑块移动轨迹
            初速度 v =0
            单位时间 t = 0.2
            位移轨迹 tracks = []
            当前位移 ccurrent = 0
            :param x:
            :return:
            '''
            # 移动轨迹, 即每次移动的距离,为一个列表,总和等于偏移量
            track = []
            # 当前位移, 也即记录当前移动了多少距离
            current = 0
            # 减速阈值, 也即开始减速的位置,这里设置为偏移量的9/10处开始减速,可以更改
            # mid = x * 4 / 5
            # 计算用的时间间隔
            t = 1
            # 初始速度
            v = 1

            while current < x:
                # if current < mid:
                #     # 当前位移小于4/5的偏移量时,加速度为2
                #     a = 1
                # else:
                #     # 当前位移大于4/5的偏移量时,加速度为-3
                #     a = -3
                # a = 0
                # # 初始速度v0
                # v0 = v
                # # 本次移动完成之后的速度v = v0 + at
                # v = v0 + a * t
                # # 本次移动距离x = v0t + 1/2 * a * t^2
                # move = v0 * t + 1 / 2 * a * t * t
                move = v * t
                # 当前位移, 这里都将move四舍五入取整
                current += round(move)
                # 将move的距离放入轨迹列表
                track.append(round(move))
                # print("轨迹列表:", track)
            return track

        def exchange(self, image):
            image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            for row in range(0, image.shape[0]):
                for col in range(0, image.shape[1]):
                    m = image[row][col]/255.00
                    if m <= 0.2700:
                        image[row][col] = 0
                    elif m > 0.2700 and m <= 0.5000:
                        image[row][col] = (m-0.27)/0.23*127
                    elif m > 0.5000 and m <= 0.7200:
                        image[row][col] = (m-0.5)/0.22*255+(0.72-m)/0.22*127
                    else:
                        image[row][col] = 255
            return image

        def identify_gap(self, bg, tp, out):
            '''
            获取缺口位置
            bg: 背景图片
            tp: 缺口图片
            out:输出图片
            '''
            # 读取背景图片和缺口图片
            bg_img = cv2.imread(bg)  # 背景图片
            tp_img = cv2.imread(tp)  # 缺口图片
            # time.sleep(1)
            # bg_img = self.exchange(bg_img)
            # tp_img = self.exchange(tp_img)

            # 识别图片边缘
            bg_edge = cv2.Canny(bg_img, 100, 200)
            tp_edge = cv2.Canny(tp_img, 100, 200)
            # 转换图片格式
            bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
            tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)

            # 缺口匹配
            res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)  # 寻找最优匹配
            # 绘制方框
            th, tw = tp_pic.shape[:2]
            tl = max_loc  # 左上角点的坐标
            br = (tl[0]+tw, tl[1]+th)  # 右下角点的坐标
            cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2)  # 绘制矩形
            cv2.imwrite(out, bg_img)  # 保存在本地
            # 返回缺口的X坐标
            # print(bg_img.shape[0])
            # if abs(bg_img.shape[0]-205) > 0:
            #     tl[0] += bg_img.shape[0]-205
            return tl[0]

        def move_slider(self,  track):
            """根据轨迹列表,拖动滑块到缺口处
            :param slider: 滑块
            :param track: 轨迹
            """
            ActionChains(self.driver.driver).click_and_hold(
                self.findelement(self.slider)).perform()
            for x in track:
                ActionChains(self.driver.driver).move_by_offset(
                    xoffset=x, yoffset=0).perform()
            ActionChains(self.driver.driver).release().perform()


    class Login_Action(VerificationCode):
        @ allure.step('输入用户名密码登录')
        def login(self, userName, userpw):
            '''
            输入用户名密码登录
            :param:userName:用户名
            :param:userpw:密码
            '''
            self.type_name(userName)
            self.type_pw(userpw)
            self.drag_slider()
            # self.quick_slider()
            self.click_login()
            assert Navigation(self.driver).get_username() == userName

        def drag_slider(self):
            '''
            第一种方法:移动滑块,完成验证
            '''
            self.hover_slider()
            name1 = self.get_img(self.bgImage)
            name2 = self.get_img(self.smallImageblocks)
            out = common.dir+"/file/temporary/out.jpg"
            x = self.identify_gap(
                name1, name2, out)
            print(x)
            if x > 200:
                x = x+20  # pass
            elif x > 150:
                x = x+16
            else:
                x = x+12  # pass
            tracks = self.get_track(x)
            self.move_slider(tracks)

        def quick_slider(self):
            '''
             第二种方法:通过接口获取验证成功
            '''
            response1 = requests.post(
                url=settings.Backstage_URL+"/share-auth/getImageVerifyCode")
            assert response1.status_code == 200
            content = json.loads(response1.text)
            for n in range(80, 230, 5):
                response = requests.get(url=settings.Backstage_URL + "/share-auth-center/validateUnlock",
                                        params={
                                            'checkMoveId': content['data']['checkMoveId'], 'xWidth': str(n)}
                                        )
                if response.text == 'true':
                    print(n)
                    break
                time.sleep(3)
            self.set_slider_success()
  • 相关阅读:
    不要轻易相信ALV
    什么是SAP Note?如何打SAP Note?
    BW作为源系统连接时,激活DSO或其他模型时提示8*数据源不存在,无法激活
    MDX Parser问题导致BO无法连通BW的解决方案
    BW中跳转报表参数传递
    SD、MM转换BI CONTENT激活错
    如何加载经过许可的第三方断字符
    把SQL Server 错误日志导出为EXCEL 并发送到指定的ftp 或者 共享盘
    tsql 调用作业
    SQL Server 2005 维护计划无法保存
  • 原文地址:https://www.cnblogs.com/ShadowXie/p/15028886.html
Copyright © 2011-2022 走看看