一、前言
selenium中有三种时间等待:
- 强制等待:
sleep
- 隐式等待:
implicitly_wait
- 显示等待:
WebDriverWait
其中,这三种方法各有优缺点:
| 元素等待方式 | 优点 | 缺点|
|–|–|–|
| sleep | 使用起来最简单,可以选择在程序调试时使用 | 浪费很多的时间,影响效率 |
| implicitly_wait | 一旦设置,在WebDriver对象实例整个周期都起到作用 | 不够灵活 |
| WebDriverWait | 节省等待时间,执行效率高 | 使用起来,难度较上两个比较高 |
二、强制等待
让程序暂停运行一定的时间,等待时间达到要求的时间后继续运行。
使用前,需要先导入time模块:
import time
在前面的文章中,已经多次使用过,这里就不做演示了。
需要注意的是,对于定位不到元素的时候,从耗时方面来讲,隐式等待
和强制等待
没什么区别。
三、隐式等待
implicitly_wait()
默认参数的单位为秒,默认值为0。
如果在最大超时时间内找到元素了,会开始执行下一操作,未找到元素,则会抛出NoSuchElementException
异常。
以百度为例:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
# 访问百度
driver.get('https://baidu.com')
start = time.time()
# 设置最大等待时间为3秒
driver.implicitly_wait(3)
try:
# 使用id定位一个不存在的元素
driver.find_element(By.ID, 'yyds')
except Exception as exception:
# 打印异常
print(exception)
# 打印程序运行时间
print(f'耗时:{time.time()-start}')
# 关闭所有页面
driver.quit()
四、显示等待
需要导入模块:
from selenium.webdriver.support.ui import WebDriverWait
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver
: 传入WebDriver实例;timeout
:指最大超时时间,默认单位为秒;poll_frequency
:调用until或until_not方法,每隔一定时间不断尝试是否能找到页面元素,默认间隔是0.5s,可自行调整间隔时间。ignored_exceptions
:超时后的异常信息,默认情况下NoSuchElementException 异常。
WebDriverWait一般和until()
和until_not()
配合使用:
until()
当某元素出现 或 某条件成立则继续执行until_not
当某元素消失 或 某条件不成立则继续执
until
或until_not
中的method参数
一定要是可以调用的对象,我们可以用selenium提供的expected_conditions
,提供一些场景的判断。
但使用expected_conditions
,需先导入:
from selenium.webdriver.support import expected_conditions as EC
常用的expected_conditions
方法如下:
方法 | 说明 |
---|---|
title_is | 判断当前页面的 title 是否完全等于(==)预期字符串 |
title_contains | 判断当前页面的 title 是否包含预期字符串 |
presence_of_element_located | 判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见 |
visibility_of_element_located | 判断元素是否可见(可见代表元素非隐藏,并且元素宽和高都不等于 0) |
visibility_of | 作用和上一个方法类似,但传入参数是定位的元素,即element |
presence_of_all_elements_located | 判断是否至少有 1 个元素存在于 dom 树中。举例:如果页面上有 n 个元素的 class 都是’qw’,那么只要有 1 个元素存在,这个方法就返回 True |
text_to_be_present_in_element | 判断某个元素中的 text 是否包含了预期的字符串 |
text_to_be_present_in_element_value | 判断某个元素中的 value 属性是否包含了预期的字符串 |
frame_to_be_available_and_switch_to_it | 判断该 frame 是否可以 switch进去,如果可以的话,返回 True 并且 switch 进去,否则返回 False |
invisibility_of_element_located | 判断某个元素中是否不存在于dom树或不可见 |
element_to_be_clickable | 判断某个元素中是否可见并且可点击 |
staleness_of | 等某个元素从 dom 树中移除,注意,这个方法也是返回 True或 False |
element_to_be_selected | 判断某个元素是否被选中了,一般用在下拉列表 |
element_selection_state_to_be | 判断某个元素的选中状态是否符合预期 |
element_located_selection_state_to_be | 跟上面的方法作用一样,只是上面的方法传入定位到的 element,而这个方法传入 locator |
alert_is_present | 判断页面上是否存在 alert |
以百度为例:
- 定位一个存在的元素:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
# 访问百度
driver.get('https://www.baidu.com')
# 设置显式等待,超时时长最大为5s,每隔1s查找元素一次
# 根据id定位到元素位置
element = WebDriverWait(driver, 5, 1).until(
EC.presence_of_element_located(('id', 'kw')))
# 在定位到的地方,输入CSDN
element.send_keys('CSDN')
- 定位一个不存在的元素
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
# 访问百度
driver.get('https://www.baidu.com')
# 设置显式等待,超时时长最大为5s,每隔1s查找元素一次
# 根据id定位到元素位置
element = WebDriverWait(driver, 5, 1).until(
EC.presence_of_element_located((By.ID, 'csdn')), message='超时了哟。。。')
得到提示:
selenium.common.exceptions.TimeoutException: Message: 超时了哟。。。