• Selenium之等待机制


    为什么需要等待

    当进行自动化测试的时候:

    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")
    driver.find_element_by_id("kw").send_keys("听雨危楼-cnblogs")
    driver.find_element_by_id("su").click()
    # import time
    # time.sleep(3)
    driver.find_element_by_link_text("听雨危楼 - 博客园").click()
    driver.quit()

    上述代码如果不睡几秒的话,很可能会报如下报错:

    selenium.common.exceptions.NoSuchElementException

    没有找到标签元素,当然,可能原因是找错了标签,但很可能是这个标签由于网速等原因迟迟没有加载出来,你就直接获取这个标签,很明显是报错,现有的简单粗暴的解决办法就是time.sleep(3),睡几秒,也就是设置线程等待,等这个标签加载出来之后,再去使用。这么着虽然简单,但是相对死板,因为我们不知道这个标签什么时候加载出来,就大概写死睡个几秒,这可以,但如果这个标签在极短的时间内就加载出来了,而你还在睡.......

    所以,可以使用selenium提供的两种等待机制:

    • 显式等待
    • 隐式等待

    先来看显式等待机制。

    显式等待机制

    上面程序解决报错使用了time模块完成,现在,使用selenium的等待机制来完成:

    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")
    driver.find_element_by_id("kw").send_keys("听雨危楼-cnblogs")
    driver.find_element_by_id("su").click()
    # driver.find_element_by_link_text("听雨危楼 - 博客园").click()
    # 没错,就是下面这行代码
    WebDriverWait(driver, 10, 0.5).until(EC.presence_of_element_located((By.LINK_TEXT, '听雨危楼 - 博客园'))).click()
    driver.quit()

    selenium提供了 WebDriverWait类实现等待机制。该类接收4个参数来指定等待机制。

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    driver = webdriver.Chrome()
    WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5, ignored_exceptions=None)

    各参数:

    • driver,浏览器驱动
    • timeout,最长超时时间,单位(秒)
    • poll_frequency,轮询检测时间,也就是每隔多少时间检测一次,默认是0.5秒
    • ignored_exceptions,超时后的异常信息,默认抛出NoSuchElementException

    WebDriverWait类提供了两个方法来完成等待机制:

    • until(self, method, message=''),method为需要提供的驱动程序,直到返回True,用的较多。
    • until_not(self, method, message=''),method为需要提供的驱动程序,直到返回False

    上面用到的method驱动程序为expected_conditions重命名后的EC,并调用其presence_of_element_located方法判断指定元素是否存在。
    expected_conditions模块提供了各种判断:

    • presence_of_element_located判断某个元素是否被加到了dom树里,并不代表该元素一定可见
    • presence_of_elements_located 判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True

    显式等待的另一种写法,首先实例化一个显式等待对象,这样可以在各个地方灵活的调用:

    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    wait = WebDriverWait(driver, 10, 0.5)  # 首先实例化一个定制好等待机制的等待对象
    driver.get("https://www.baidu.com")
    driver.find_element_by_id("kw").send_keys("听雨危楼-cnblogs")
    driver.find_element_by_id("su").click()
    # WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5, ignored_exceptions=None).until(EC.presence_of_element_located((By.LINK_TEXT, '听雨危楼 - 博客园'))).click()
    wait.until(EC.presence_of_element_located((By.LINK_TEXT, '听雨危楼 - 博客园'))).click()
    driver.quit()

    一般的,推荐上述这种方式,比较灵活嘛。

    隐式等待机制

    与显式等待不同的是,隐式等待我们可以直接通过浏览器驱动对象调用,并且用法也相对简单:

    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.implicitly_wait(time_to_wait=10)   # 只需要一个等待超时时间参数
    driver.get("https://www.baidu.com")
    driver.find_element_by_id("kw").send_keys("听雨危楼-cnblogs")
    driver.find_element_by_id("su").click()
    driver.find_element_by_link_text('听雨危楼 - 博客园').click()
    driver.quit()

    implicitly_wait等待时间单位为秒,如上例所示,指定了10秒。需要注意的是,隐式与显式等待有明显的区别,隐式等待应用于全局,每当使用driver驱动找某个元素时,隐式等待机制就会被触发(导致测试速度变慢),如果元素存在,则继续执行,否则,它将以轮询的方式判断元素是否定位成功,直至等待超时,抛出错误NoSuchElementException。而显式等待则只是指定某(些)个元素是否存在时执行。

    休眠机制

    最后,使用Python提供的休眠机制(也就是time模块啦),这没啥可说的,睡就完了,想在哪等就在哪等.......

    import time
    
    time.sleep(1)

    在等待机制的选择上,我们可以在三种等待机制中灵活选择:

    • 普通(静态页面较多)网页,休眠机制和显式等待机制可以相互搭配,提高效率。
    • 动态页面较多的时候,隐式等待就排上用场了。当然,懒人法则就用隐式等待。一劳永逸.....


    see also:python selenium expected_conditions使用实例 | implicitly_wait()隐式等待

  • 相关阅读:
    Window7下手动编译最新版的PCL库
    C和C++中的异常处理
    队列之卡片游戏
    C/C++笔记
    最真的梦——文/林清玄
    库函数与系统调用的区别
    hdu2653之BFS
    使用ffmpeg+crtmpserver搭建文件的伪直播
    ZOJ3705:Applications
    c_c++基础问题(平时读书时笔记)
  • 原文地址:https://www.cnblogs.com/sundawei7/p/11959160.html
Copyright © 2020-2023  润新知