首页 > 解决方案 > 使用 @contextmanager 和 yield 以等待页面加载

问题描述

我正在使用基于此博客文章(最后一部分)的以下代码:

from selenium.webdriver.support.expected_conditions import staleness_of
from selenium.webdriver.support.ui import WebDriverWait

@contextmanager
def wait_for_page_load(self, timeout=15):
    old_page = self.driver.find_element_by_tag_name('html')
    yield
    WebDriverWait(self.driver, timeout).until(staleness_of(old_page))

self.driverselenium webdriver 对象在哪里。
然后可以在with块中使用此上下文管理器:

def click_on_the_link():
    with self.wait_for_page_load():
        self.driver.find_element_by_link_text('a link')

我理解的方式是存储旧页面,如果新页面尚未加载,则会创建一个 WebDriverWait 对象,该对象等待站点加载后再继续。然后执行新页面上的动作,例如点击一个链接。

但是,代码对我来说没有意义。根据文档

在生成器产生的地方,嵌套在 with 语句中的块被执行。然后在退出块后恢复生成器。

with假设博文中的代码是正确的,如果语句中的代码先执行,该方法怎么可能等待站点加载?

标签: pythonseleniumselenium-webdrivercontextmanager

解决方案


因为它使用显式等待

WebDriverWait(self.driver, timeout).until(staleness_of(old_page))

这将等到 contitionstaleness_of成功或在达到超时时抛出异常。由于此代码在 之后执行,因此yield与驱动程序的任何操作都会被此捕获。

更新

如果您只想让您的驱动程序等待a link您可以WebDriverWait直接使用的元素

def click_on_the_link(self):
    wait = WebDriverWait(self.driver, 10)
    wait.until(element_to_be_clickable('a link'))
    self.driver.find_element_by_link_text('a link')

推荐阅读