这是我用Python尝试的一种完全通用的解决方案:
首先是一个通用的“等待”函数(如果您喜欢,可以使用WebDriverWait,但我认为它们很丑):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
接下来,解决方案依赖于Selenium记录页面上所有元素(包括顶级<html>
元素)的(内部)ID号。当页面刷新或加载时,它会获得一个新的带有新ID的html元素。
因此,假设您想单击一个名为“my link”的链接:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
为了使代码更Python化、可重用和通用化,您可以创建一个上下文管理器:
from contextlib import contextmanager
@contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
然后您几乎可以在任何Selenium交互中使用它:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
我认为那是防弹的!你觉得呢?
这里有一篇关于它的博客文章提供更多信息。