使用 Selenium Webdriver 检测一段时间后是否找不到元素
Detect if element wasn't found after some time using Selenium Webdriver
我每隔几秒钟就会多次连接到一个网站,有时网站会进入一个巨大的加载阶段,大约需要 5 分钟才能停止加载。当它最终停止时,它抛出一个预期的 ElementNotFoundException
然后我捕获并从最后一点重新启动该过程。但是,我希望能够检测到这个加载阶段并尽快处理它,而不是等待 5 分钟让它结束。我尝试使用 FluentWait
实现和 WebDriverWait
实现,但 none 目前有效。这是我尝试过的两种实现方式:
流利等待:
private static WebElement fluentWait(final By locator, WebDriver driver) {
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(10, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS);
//.ignoring(NoSuchElementException.class);
return wait.until((Function<WebDriver, WebElement>) driver1 -> {
assert driver1 != null;
return driver1.findElement(locator);
});
}
WebDriverWait:
new WebDriverWait(driver,5).until(ExpectedConditions.presenceOfElementLocated(new By.ByCssSelector(someSelector)));
P.S:我正在使用 Selenium Webdriver,特别是 ChromeDriver()
。这是网站进入巨大加载阶段时的外观图像 ->
根据我收集到的你的问题,如果在此之前执行尚未完成,你想让代码等待特定的时间和超时吗?
如果你想这样做,我认为最好的方法是实现一个简单的 class,它使用一个执行器来等待结果。执行器支持超时,并且能够 return 一个值或者如果执行时间太长则抛出异常。
为此我写了这个简单的 class:
public class TimedWait<T> {
public T run(Callable<T> run, long timeoutMs) throws TimeoutException, ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
return executor.invokeAny(Collections.singletonList(run), timeoutMs, TimeUnit.MILLISECONDS);
}
}
这将使用我提到的超时,并将 运行 提供的具有指定超时的 Callable,之后会抛出异常。
它如何运行的示例如下(出于示例目的,我确实做了一些快速而肮脏的异常处理,您可能需要稍微清理一下以避免过度使用 try catch)
public void run() {
try {
String result = new TimedWait<String>().run(() -> {
Thread.sleep(500);
return "Some Result";
}, 1000L);
System.out.println(result);
String timeOut = new TimedWait<String>().run(() -> {
Thread.sleep(1500);
return "This will time out";
}, 1000L);
System.out.println(timeOut);
} catch (Exception e) {
e.printStackTrace();
}
}
由于在这个例子中第一次输出的延迟小于超时,结果将被打印出来。对于第二个输出,延迟大于超时导致异常。
输出为:
Some Result
java.util.concurrent.TimeoutException
这没什么好担心的。您可以查看以下链接,希望对您有所帮助。
Selenium -- How to wait until page is completely loaded
Wait for page load in Selenium
我每隔几秒钟就会多次连接到一个网站,有时网站会进入一个巨大的加载阶段,大约需要 5 分钟才能停止加载。当它最终停止时,它抛出一个预期的 ElementNotFoundException
然后我捕获并从最后一点重新启动该过程。但是,我希望能够检测到这个加载阶段并尽快处理它,而不是等待 5 分钟让它结束。我尝试使用 FluentWait
实现和 WebDriverWait
实现,但 none 目前有效。这是我尝试过的两种实现方式:
流利等待:
private static WebElement fluentWait(final By locator, WebDriver driver) {
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(10, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS);
//.ignoring(NoSuchElementException.class);
return wait.until((Function<WebDriver, WebElement>) driver1 -> {
assert driver1 != null;
return driver1.findElement(locator);
});
}
WebDriverWait:
new WebDriverWait(driver,5).until(ExpectedConditions.presenceOfElementLocated(new By.ByCssSelector(someSelector)));
P.S:我正在使用 Selenium Webdriver,特别是 ChromeDriver()
。这是网站进入巨大加载阶段时的外观图像 ->
根据我收集到的你的问题,如果在此之前执行尚未完成,你想让代码等待特定的时间和超时吗?
如果你想这样做,我认为最好的方法是实现一个简单的 class,它使用一个执行器来等待结果。执行器支持超时,并且能够 return 一个值或者如果执行时间太长则抛出异常。
为此我写了这个简单的 class:
public class TimedWait<T> {
public T run(Callable<T> run, long timeoutMs) throws TimeoutException, ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
return executor.invokeAny(Collections.singletonList(run), timeoutMs, TimeUnit.MILLISECONDS);
}
}
这将使用我提到的超时,并将 运行 提供的具有指定超时的 Callable,之后会抛出异常。
它如何运行的示例如下(出于示例目的,我确实做了一些快速而肮脏的异常处理,您可能需要稍微清理一下以避免过度使用 try catch)
public void run() {
try {
String result = new TimedWait<String>().run(() -> {
Thread.sleep(500);
return "Some Result";
}, 1000L);
System.out.println(result);
String timeOut = new TimedWait<String>().run(() -> {
Thread.sleep(1500);
return "This will time out";
}, 1000L);
System.out.println(timeOut);
} catch (Exception e) {
e.printStackTrace();
}
}
由于在这个例子中第一次输出的延迟小于超时,结果将被打印出来。对于第二个输出,延迟大于超时导致异常。
输出为:
Some Result
java.util.concurrent.TimeoutException
这没什么好担心的。您可以查看以下链接,希望对您有所帮助。
Selenium -- How to wait until page is completely loaded
Wait for page load in Selenium