5. selenium - 三种等待方式原理剖析和场景应用

前言

UI 自动化一大困难点就是元素定位,而且最不稳定的就是页面,定位方法没问题,但是有时候网络不好,页面加载慢,也会导致找不到元素。

找不到元素的时候selenium 会抛出类似的异常,NoSuchElementException

为了解决页面等待问题,selenium 也专门设计了一些方法来进行页面等待,等待页面加载完成才开始定位元素,这样的话就会大大降低找不到元素的异常。


等待方式有三种:

  1. Sleep 固定等待,等待时间到了,不管页面有没有加载完成,都会进行下一步。
  2. 隐式等待,implicitly_wait()。等待页面元素全部加载完成,进行下一步操作。
  3. 显式等待,WebDriverWait()。等待特定某个元素加载完成,进行下一步。

一、sleep 固定等待

在自动化测试过程中,不要用 sleep 方法进行等待,这样会导致整个项目的自动化测试无线延长,不建议使用。但是在调试脚本的时候可以使用,方便快捷。

from selenium import webdriver
from time import sleep                   # 导入sleep
driver = webdriver.Chrome()

url = 'https://movie.douban.com/'
driver.get(url)

sleep(5)                                 # 等待 5 s
driver.find_element_by_name('search_text').send_keys('蜘蛛侠')

sleep(2)

driver.quit()                            # 关闭浏览器 


二、implicitly_wait

隐式等待是通过一定的时长等页面元素全部加载完成(就是等待页面左上角转圈结束)。如果超出了设置的时长,元素还没有加载出来,那么就会抛出异常 NoSuchElementException。

否则一直等到时间结束,这里有不好的地方,因为 JavaScript 一般是放在 body 的最后进行加载,需要的元素加载完成了,我们却在等待页面全部加载完成,也是浪费时间。

隐式等待对整个 driver 周期都起作用,在最开始设置一次就可以了。

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
driver = webdriver.Chrome()

# 设置隐式等待,最多等待 10 s,如果 10s内什么时候加载完毕就什么时候进行操作
driver.implicitly_wait(10)

try:
    url = 'https://movie.douban.com/'
    driver.get(url)
    driver.find_element_by_name('search_text').send_keys('蜘蛛侠')

except NoSuchElementException as msg:
    print(msg)

# 关闭浏览器
driver.quit()


三、 显式等待 - WebDriverWait()

显式等待是针对某一个元素进行等待判定,隐式等待是等待页面上全部加载完成,所以显式等待更加好,也是最常用的一种等待方式。

WebDriverWait 是 selenium 提供显式等待的模块。

class WebDriverWait(object):
    def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
        """Constructor, takes a WebDriver instance and timeout in seconds.

           :Args:
            - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
            - timeout - Number of seconds before timing out
            - poll_frequency - sleep interval between calls
              By default, it is 0.5 second.
            - ignored_exceptions - iterable structure of exception classes ignored during calls.
              By default, it contains NoSuchElementException only.

           Example:
            from selenium.webdriver.support.ui import WebDriverWait \n
            element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
            is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
                        until_not(lambda x: x.find_element_by_id("someId").is_displayed())

参数说明:

-driver            : 传入 WebDriver 实例
-timeout           : 超时时间,等待的最长时间
-poll_frequency    : 调用 until 或until_not 中的方法的间隔时间,默认是 0.5 s
-ignored_exceptions: 忽略的异常

这个模块中,有两种方法 until 和 until_not。

-method  : 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是 False
-message : 如果超时,抛出 TimeoutException,讲 message 传入异常。

例子1:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()

url = 'https://movie.douban.com/'
driver.get(url)

# 一共等待 10s,每 0.5 查找一次,直到找到name 为 search_text 的元素。
element = WebDriverWait(driver, 10, 0.5).until(lambda x: x.find_element_by_name("search_text"))
element.send_keys('蜘蛛侠')


例子2

方式二、

看看 expected_conditions 的源码,按住 ctrl 键,鼠标点击就可以过去源码这里。
有判断 title 的方法,有url 的,也有 alert 弹窗的,根据实际情况选择即可。


from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()

url = 'https://movie.douban.com/'
driver.get(url)

# 最多等待 5 s,每 0.5 秒查找一次。
wait = WebDriverWait(driver, 5, 0.5)
# 直到在这个页面出现 title 为 豆瓣电影
wait.until(EC.title_is('豆瓣电影'))

driver.find_element_by_name('search_text').send_keys('蜘蛛侠')

posted @ 2022-03-27 01:56  西瓜_皮  阅读(380)  评论(0编辑  收藏  举报