Demonstration of three waiting methods of selenium.
- mandatory wait
- implicit wait
- explicit wait
mandatory wait
import time
# 整个程序强制等待 3 秒
time.sleep(3)
implicit wait
Set a global wait time to implicitly wait for an element to be found or for a command to complete. This method only needs to be called once per session.
# Amount of time to wait (in seconds)
driver.implicitly_wait(3)
explicit wait
Define the waiting conditions, and continue to execute when the conditions are met, otherwise continue to wait, and throw an exception after a timeout. A more flexible waiting method, the most commonly used waiting method in projects.
The display wait class WebDriverWait
initialization receives four parameters :
driver
: automated drivetimeout
: total waiting timepoll_frequency
: polling intervalignored_exceptions
: ignore expected exception type
Two judgment conditions:
def until(self, method, message=''):
"""
调用传入的方法作为参数,直到返回值不是 False
"""
def until_not(self, method, message=''):
"""
调用传入的方法作为参数,直到返回值为 False
"""
example
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import StaleElementReferenceException
class TestWait:
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.get("https://www.baidu.com")
self.driver.implicitly_wait(5) # 隐式等待
def teardown_class(self):
self.driver.quit()
def test_sleep(self):
""" 强制等待
无论元素是否出现都强制等待
"""
ele = self.driver.find_element(By.ID, "kw")
time.sleep(10)
ele.send_keys("hello")
def test_implicitly_wait(self):
""" 隐式等待
设置在初始化 driver 处,元素 5 秒不出现才报错
"""
ele = self.driver.find_element(By.ID, "test") # 随便设置个元素
ele.click()
def test_webdriver_wait_by_def(self):
""" 显式等待
自定义方法编写条件
"""
def wait(x): # 参数为必传项
hot_search_items = self.driver.find_elements(
By.XPATH, '//*[@class="title-content-title"]'
)
return len(hot_search_items) == 6
# 等待百度热搜出现 6 条则继续向下执行,否则最大等待时间为 10 秒,0.5 秒轮询一次
WebDriverWait(self.driver, 10).until(wait)
def test_webdriver_wait_by_ec(self):
""" 显式等待
使用预置的等待条件库 expected_conditions
"""
# 等待热搜词可点击才继续向下执行,否则最大等待时间为 10 秒,每秒轮询一次
WebDriverWait(self.driver, 1, 10).until(
expected_conditions.element_to_be_clickable(
(By.XPATH, '//*[@class="title-content-title"]')
)
)
def test_webdriver_wait_until_not(self):
""" 显式等待
每 5 秒看一次该元素是否展示,如果不展示则用例直接通过
"""
WebDriverWait(self.driver, 5, 10).until_not(
expected_conditions.element_to_be_clickable(
(By.XPATH, 'hello')
)
)
def test_webdriver_wait_ignored_exceptions(self):
""" 显式等待
忽略某种预期内的异常,继续轮询等待
"""
WebDriverWait(self.driver, 1, 5, StaleElementReferenceException).until(
# 可以在 WebDriverWait 初始化时添加忽略异常, 如上当页面元素未更新时也不会报错,继续轮询
# 默认为 NoSuchElementException
expected_conditions.element_to_be_clickable(
(By.ID, "test")
)
)
expected_conditions API
"""
* Canned "Expected Conditions" which are generally useful within webdriver
* tests.
"""
class title_is(object):
"""标题完全匹配,返回 bool"""
class title_contains(object):
"""标题包含匹配,区分大小写"""
class url_contains(object):
"""url 片段匹配,区分大小写,返回 bool"""
class url_matches(object):
"""url 正则匹配,返回 bool"""
class url_to_be(object):
"""url 精确匹配,返回 bool"""
class url_changes(object):
"""url 不匹配则为真,否则为假"""
class presence_of_element_located(object):
"""页面元素是否存在,并不一定可见,接收一个 locator"""
class visibility_of_element_located(object):
"""元素是否在页面中必须展示,且高度宽度大于0,接收一个 locator"""
class visibility_of(object):
"""元素是否可见,可见则返回元素,否则返回 false"""
class presence_of_all_elements_located(object):
"""查找一组元素,无论是否在页面可见"""
class visibility_of_any_elements_located(object):
"""查找一组元素,返回该元素中所有在页面可见的元素"""
class visibility_of_all_elements_located(object):
"""查找一组元素,该元素都页面中可见"""
class text_to_be_present_in_element(object):
"""检查指定文本是否存在于元素的文本当中"""
class text_to_be_present_in_element_value(object):
"""检查指定文本是否存在于元素的属性值当中"""
class frame_to_be_available_and_switch_to_it(object):
"""检查是否可以切换到指定 locator 的 frame 当中"""
class invisibility_of_element_located(object):
""" 元素在页面中不可见或不存在 """
class element_to_be_clickable(object):
"""元素是否可被点击"""
class staleness_of(object):
"""元素是否停止加载,依然加载返回 false,否则为 true"""
class element_to_be_selected(object):
"""获取元素对象的 is_selected 属性"""
class element_located_to_be_selected(object):
"""通过 locator 定位元素,获取该元素的 is_selected 属性"""
class element_selection_state_to_be(object):
"""当前元素是否为选中状态"""
class element_located_selection_state_to_be(object):
"""当前元素是否可被选中"""
class number_of_windows_to_be(object):
"""判断当前浏览器窗口数量"""
class new_window_is_opened(object):
"""检查是否打开了一个新窗口"""
class alert_is_present(object):
"""alert 弹窗是否chu'xian"""
Explicit wait + window switching official example
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
with webdriver.Chrome() as driver:
# Open URL
driver.get("https://www.baidu.com")
# Setup wait for later
wait = WebDriverWait(driver, 10)
# Store the ID of the original window
original_window = driver.current_window_handle
# Check we don't have other windows open already
assert len(driver.window_handles) == 1
# Click the link which opens in a new window
driver.find_element(By.LINK_TEXT, "新闻").click()
# Wait for the new window or tab
wait.until(EC.number_of_windows_to_be(2))
# Loop through until we find a new window handle
for window_handle in driver.window_handles:
if window_handle != original_window:
driver.switch_to.window(window_handle)
break
# Wait for the new tab to finish loading content
wait.until(EC.title_is("百度新闻——海量中文资讯平台"))