ui自动化实现浏览器登陆(python+selenium)

还在保存网址,手动输入账号密码,来做测试么?
不,我已经开始用脚步来自动登陆了。

测试代码示例

先看一段测试代码

def test(self):
    driver.get("https://网址保密哈哈")
    driver.maximize_window()
    loginIdInput.sendKeys(123456)
    submitButton.click()
    userPhone.sendKeys('hahaha')
    userPassword.sendKeys('123')
    captcha.sendKeys('8888')
    # self.manualCredential('123')
    credential.click()
    po(By.XPATH, '/html/body/div/div/section/header/div[3]/a/span').hover()
    po(By.XPATH, '/html/body/div[2]/div/div/ul/li[1]/div').click()

现在看不懂没关系,先有个印象,接下来我逐步做讲解。

代码结构设计

只是做登陆,就设计了简易版的po模式。

ui自动化实现浏览器登陆(python+selenium)

po代码解析

__init__()

# 初始化
def __init__(self, by=None, value=None):
    self.by = by
    self.value = value
    self.element = None

by value参考的原生find_element的参数:

def find_element(self, by=By.ID, value=None):
    """
    Find an element given a By strategy and locator. Prefer the find_element_by_* methods when
    possible.

    :Usage:
        element = driver.find_element(By.ID, 'foo')

    :rtype: WebElement
    """

源码中也有By的解释:

class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"

于是,就可以这样来定义一个页面元素

loginIdInput = po(By.XPATH, '//*[@id="loginIdInput"]')

也可以这样来操作一个临时元素

po(By.XPATH, '/html/body/div[2]/div/div/ul/li[1]/div').click()

findElement() & isElementExist()

def findElement(self):
    # 元素往往需等待加载,这里设置最多等待30s
    self.element = WebDriverWait(driver, 30, 1).until(EC.presence_of_element_located((self.by, self.value)))
    return self.element
def isElementExist(self, by, value):
    # 判断元素是否存在,常用作断言
    try:
        driver.find_element(by, value)
        return True
    except:
        return False

其他

def sendKeys(self, s):
    # send_keys
    self.findElement()
    self.element.send_keys(s)

def click(self):
    # click
    self.findElement()
    for i in range(5):
        try:
            self.element.click()
            return
        except:  # 有可能出现加载遮罩无法点击
            time.sleep(1)
            continue

def getAttribute(self, t):
    # get_attribute
    self.findElement()
    return self.element.get_attribute(t)

def hover(self):
    # 鼠标悬浮
    for i in range(30):
        if self.findElement().is_displayed():
            # action = ActionChains(driver)
            action.move_to_element(self.element).perform()
            return
        time.sleep(1)
    raise RuntimeError(f'hover找不到元素{self.value}')

聪明的你,一定发现了:

1、主要封装的是一些异常处理
2、命名统一采用了驼峰方式,比如send_keys sendKeys,个人习惯哈哈哈

loginBrowser.py

再看下之前的测试代码,是不是清晰了些许

def test(self):
    driver.get("https://网址保密哈哈")
    driver.maximize_window()
    loginIdInput.sendKeys(123456)
    submitButton.click()
    userPhone.sendKeys('hahaha')
    userPassword.sendKeys('123')
    captcha.sendKeys('8888')
    # self.manualCredential('123')
    credential.click()
    po(By.XPATH, '/html/body/div/div/section/header/div[3]/a/span').hover()
    po(By.XPATH, '/html/body/div[2]/div/div/ul/li[1]/div').click()

driver是这样定义的:driver = webdriver.Firefox()

慢!这博客也写的太不走心了,还有注释代码?

# self.manualCredential('123')

其实不然,这个是这里的重点:验证码。
如果是由万能验证码的,captcha.sendKeys('8888')就搞定了。
如果没有呢,比如灰度环境、线上环境往往出于安全考虑不会设置。
有一个方法,就是图片破解,把验证码图片获取下来,进行识别。这个方法的弊端在于简单的图片是可以在网上搜代码来破解的,复杂点的就需要付费工具。而且公司的验证码我眼睛看着输都经常输错,破解的准确率就很不靠谱了。
那么,办法只有一个,就是传统的,手动!

上代码:

def manualCredential(self, pwd):
    # 手动输验证码
    while True:
        if len(str(captcha.getAttribute('value'))) == 4:
            credential.click()
        if not po().isElementExist(By.XPATH, '//*[@id="credential"]/button'):
            break
        time.sleep(1)
        if str(userPassword.getAttribute('value')) == "":
            userPassword.sendKeys(pwd)

ui自动化实现浏览器登陆(python+selenium)

代码逻辑是这样的:

每隔1s轮询页面情况
当验证码输入框有4个字符,就点击登录
如果验证码正确,断言登录按钮消失,轮询结束
如果验证码错误(一般会清空密码),重新设置密码,继续轮询
上一篇:selenium 元素操作(四)


下一篇:05. 线性表——顺序表,按值查找,按位查找(查)