如何让 Selenium 2.0 等待页面加载?
如何让 Selenium 2.0 等待页面加载?
你也可以使用以下代码检查页面是否已加载
IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
使用 WebDriverWait 类。
此外,这里 也可以参考。
您可以期望展示某些元素。例如在C#中:
WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));
_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement")));
JavaWebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfAllElements(list));
其中list是元素的ArrayList。 - Mario GaleafindElement
方法,WebDriver将对该元素进行轮询,直到找到该元素或达到超时值。driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
来源:隐式等待
通常情况下,使用Selenium 2.0时,Web Driver应该在确定页面已加载后才将控制权返回给调用代码。如果没有加载完成,您可以调用waitforelement
,它会循环调用findelement
直到找到元素或超时(超时时间可以设置)。
JavascriptExecutor
添加了一个等待,等待文档的readyState变为"complete"。因为从Selenium到浏览器的往返,竞争条件得以缓解,所以这对我来说“总是”有效。在“click()”之后,当我期望页面加载时,我明确等待(使用WebDriverWait)readyState。 - dmansfieldRuby 实现:
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
@driver.execute_script("return document.readyState;") == "complete"
}
所有这些解决方案对于特定情况都可以,但它们都会有至少一个可能的问题:
它们不够通用--它们要求您提前知道某些特定条件将成立(例如将显示某个元素)
它们容易出现竞争条件,您可能会在旧页面和新页面上同时使用同一个元素。
以下是我尝试提供的一个通用解决方案(使用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记录页面上所有元素的(内部)id编号,包括顶级<html>
元素。当页面刷新或加载时,它会得到一个具有新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代码更加Pythonic、可重复使用和通用化,可以使用上下文管理器(context manager):
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()
我认为那是防弹的!你觉得呢?
您可以删除System.out
行。它是为了调试目的而添加的。
WebDriver driver_;
public void waitForPageLoad() {
Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
wait.until(new Function<WebDriver, Boolean>() {
public Boolean apply(WebDriver driver) {
System.out.println("Current Window State : "
+ String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
return String
.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
.equals("complete");
}
});
}
这里是一份Java 8版本的目前最赞回答:
WebDriverWait wait = new WebDriverWait(myDriver, Duration.ofSeconds(15));
wait.until(webDriver -> "complete".equals(((JavascriptExecutor) webDriver)
.executeScript("return document.readyState")));
其中 myDriver
是一个WebDriver
对象(之前声明过)。
注意:请注意,此方法(document.readyState
)仅检查DOM。
WebDriverWait(drive, long)
is deprecated so use WebDriverWait(drive, duration)
ex:-
import java.time.Duration; WebDriverWait(driver, Duration.ofSeconds(5));
- Isuru DilshanImran的答案被转化为Java 7版:
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver wdriver) {
return ((JavascriptExecutor) driver).executeScript(
"return document.readyState"
).equals("complete");
}
});
你还可以使用类:ExpectedConditions
来显式等待网页上的元素出现,然后再执行进一步的操作。
你可以使用ExpectedConditions
类来确定一个元素是否可见:
WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));
请查看ExpectedConditions类的Javadoc
以获取您可以检查的所有条件列表。