我正试图在selenium中检查网页是否已加载完成(即检查是否已加载所有控件)。
我尝试了以下代码:
new WebDriverWait(firefoxDriver, pageLoadTimeout).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
但即使页面加载上面的代码也不会等待。
我知道我可以检查特定元素以检查其是否可见/可点击等,但我正在寻找一些通用解决方案
答案 0 :(得分:3)
正如您所提到的,如果有任何通用功能来检查页面是否已在Selenium中完全加载,答案是否。
首先让我们看一下您的代码试用,如下所示:
new WebDriverWait(firefoxDriver, pageLoadTimeout).until(webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
上述代码行中的参数pageLoadTimeout
并非真正与实际pageLoadTimeout()相似。
您可以在此处找到pageLoadTimeout in Selenium not working
的详细讨论现在,当您的用例与完全加载的网页相关时,您可以使用pageLoadStrategy()设置为 normal
[支持的值 DesiredCapabilities 类或 ChromeOptions 类的实例使用
使用 DesiredCapabilities 类:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
public class myDemo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
DesiredCapabilities dcap = new DesiredCapabilities();
dcap.setCapability("pageLoadStrategy", "normal");
FirefoxOptions opt = new FirefoxOptions();
opt.merge(dcap);
WebDriver driver = new FirefoxDriver(opt);
driver.get("https://www.google.com/");
System.out.println(driver.getTitle());
driver.quit();
}
}
使用 ChromeOptions 类:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.PageLoadStrategy;
public class myDemo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
FirefoxOptions opt = new FirefoxOptions();
opt.setPageLoadStrategy(PageLoadStrategy.NORMAL);
WebDriver driver = new FirefoxDriver(opt);
driver.get("https://www.google.com/");
System.out.println(driver.getTitle());
driver.quit();
}
}
您可以在Page load strategy for Chrome driver (Updated till Selenium v3.12.0)
中找到详细的讨论现在将 PageLoadStrategy 设置为 NORMAL ,您的代码试用版确保浏览器客户端具有(即 Web浏览器)已达到'document.readyState'
等于"complete"
。一旦满足这个条件,Selenium就会执行下一行代码。
您可以在Selenium IE WebDriver only works while debugging
中找到详细的讨论但浏览器客户端获得'document.readyState'
等于"complete"
仍然不能保证所有 JavaScript 和 Ajax电话已完成。
要等待所有 JavaScript 和 Ajax Calls 完成,您可以编写如下函数:
public void WaitForAjax2Complete() throws InterruptedException
{
while (true)
{
if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
break;
}
Thread.sleep(100);
}
}
您可以在Wait for ajax request to complete - selenium webdriver
中找到详细的讨论现在,通过 PageLoadStrategy 和"return jQuery.active == 0"
的上述两种方法看起来都在等待无限期事件。因此,对于明确的等待,您可以WebDriverWait将ExpectedConditions设置为titleContains()方法,以确保页面标题(即网页) )是可见的,并假设所有元素也可见如下:
driver.get("https://www.google.com/");
new WebDriverWait(driver, 10).until(ExpectedConditions.titleContains("partial_title_of_application_under_test"));
System.out.println(driver.getTitle());
driver.quit();
现在,有时虽然页面标题可以匹配您的应用程序标题,但您想要交互的所需元素仍然无法完成加载。因此,更细粒度的方法是将WebDriverWait与ExpectedConditions设置为visibilityOfElementLocated()方法联系起来,这将使您的程序等待所需的元素可见如下:
driver.get("https://www.google.com/");
WebElement ele = new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath_of_the_desired_element")));
System.out.println(ele.getText());
driver.quit();
答案 1 :(得分:0)
我也使用selenium而且我遇到了同样的问题,要解决这个问题我还要等待jQuery加载。
因此,如果您遇到同样的问题,请尝试此操作
((Long) ((JavascriptExecutor) browser).executeScript("return jQuery.active") == 0);
您可以将两个函数包装在一个方法中并检查,直到加载了页面和jQuery
答案 2 :(得分:0)
实现这一点,它为包括我在内的许多人工作。它包括JavaScript页面等待,Angular,JQuery,如果它在那里。
如果您的应用包含Javascript& JQuery你只能为那些编写代码,
通过单一方法定义它,您可以在任何地方调用它:
// Wait for jQuery to load
{
ExpectedCondition<Boolean> jQueryLoad = driver -> ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active") == 0);
boolean jqueryReady = (Boolean) js.executeScript("return jQuery.active==0");
if (!jqueryReady) {
// System.out.println("JQuery is NOT Ready!");
wait.until(jQueryLoad);
}
wait.until(jQueryLoad);
}
// Wait for ANGULAR to load
{
String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0";
ExpectedCondition<Boolean> angularLoad = driver -> Boolean.valueOf(((JavascriptExecutor) driver).executeScript(angularReadyScript).toString());
boolean angularReady = Boolean.valueOf(js.executeScript(angularReadyScript).toString());
if (!angularReady) {
// System.out.println("ANGULAR is NOT Ready!");
wait.until(angularLoad);
}
}
// Wait for Javascript to load
{
ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) driver).executeScript("return document.readyState").toString()
.equals("complete");
boolean jsReady = (Boolean) js.executeScript("return document.readyState").toString().equals("complete");
// Wait Javascript until it is Ready!
if (!jsReady) {
// System.out.println("JS in NOT Ready!");
wait.until(jsLoad);
}
}
让我知道你是否坚持实施。
它克服了线程或显式等待的使用。
答案 3 :(得分:0)
public static void waitForPageToLoad(long timeOutInSeconds) {
ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
};
try {
System.out.println("Waiting for page to load...");
WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeOutInSeconds);
wait.until(expectation);
} catch (Throwable error) {
System.out.println(
"Timeout waiting for Page Load Request to complete after " + timeOutInSeconds + " seconds");
}
}
试试这个方法
答案 4 :(得分:0)
类似这样的方法应该起作用(请原谅java回答中的python):
idle = driver.execute_async_script("""
window.requestIdleCallback(() => {
arguments[0](true)
})
""")
这应该阻塞,直到事件循环空闲为止,这意味着应该加载所有资产。
答案 5 :(得分:0)
这对我来说很适合动态呈现的网站:
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true
}
catch (TimeoutException te) {
}
String script = "return document.getElementsByTagName(\"html\")[0].outerHTML;";
content = ((JavascriptExecutor) driver).executeScript(script).toString();
答案 6 :(得分:0)
有一种简单的方法可以做到。当您第一次通过 javascript 请求状态时,它告诉您页面是 complete
,但之后它进入状态 loading
。第一个 complete
状态是初始页面!
所以我的建议是在 complete
状态之后检查 loading
状态。在 PHP 中检查这段代码,很容易翻译成另一种语言。
$prevStatus = '';
$checkStatus = function ($driver) use (&$prevStatus){
$status = $driver->executeScript("return document.readyState");
if ($prevStatus=='' && $status=='loading'){
//save the previous status and continue waiting
$prevStatus = $status;
return false;
}
if ($prevStatus=='loading' && $status=='complete'){
//loading -> complete, stop waiting, it is finish!
return true;
}
//continue waiting
return false;
};
$this->driver->wait(20, 150)->until($checkStatus);
检查元素是否存在也很有效,但您需要确保该元素仅存在于目标页面中。