我正在尝试使用Selenium等待进度条出现和消失,这表明搜索结果已经开始并且已经完成。
没有进度条时,文档看起来像这样:
<html lang="en-US">
<body class="appian-body">
<a id="skip-to-content"></a>
<div id="aDiv"></div>
<div id="anotherOne"></div>
<div id="OneMore"></div>
...
</body>
</html>
搜索通话开始时,看起来像这样:
<html lang="en-US">
<body class="appian-body">
<a id="skip-to-content"></a>
<div id="aDiv"></div>
<div id="anotherOne"></div>
<div id="OneMore"></div>
...
<div id="appian-working-indicator-hidden" style="display: none;"></div>
</body>
</html>
请注意<div id="appian-working-indicator-hidden" style="display: none;"></div>
已经出现,这也是进度条出现的时候。当然,搜索完成后它就会消失,然后我们回到原始文档。
以下是我为等待该元素而做的一些尝试:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div[4]")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("/html/body/div[4]")));
结果:visibilityOfElementLocated
上的超时异常(即从不可见)。
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("/html/body/div[4]")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("/html/body/div[4]")));
结果:执行完全通过presenceOfElementLocated
和invisibilityOfElementLocated
进行,而无需等待。
那么,还可以做些什么来确保此元素出现和消失?
我创建了这些递归方法:
public void waitForProgressBarToStart() {
List<WebElement> progressBarList = driver.findElements(By.xpath("//div[@id='appian-working-indicator-hidden']"));
if(progressBarList.size() == 0) {
waitForProgressBarToStart();
} else {
//for timestamping when the element is found
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
System.out.println(String.format("%s: Progress Bar started", dateFormat.format(date)));
}
}
public void waitForProgressBarToFinish() {
List<WebElement> progressBarList = driver.findElements(By.xpath("//div[@id='appian-working-indicator-hidden']"));
if(progressBarList.size() > 0) {
waitForProgressBarToFinish();
} else {
//for timestamping when the element is gone
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
System.out.println(String.format("%s: Progress Bar done", dateFormat.format(date)));
}
}
public void waitForResults(){
waitForProgressBarToStart();
waitForProgressBarToFinish();
}
在方法中使用了时间戳记后,我可以看到waitForProgressBarToFinish
方法比实际进度条花费10-13秒的时间。 waitForProgressBarToStart
似乎在正确的时间找到了元素。
waitForProgressBarToFinish
为什么需要更长的时间以及如何解决?
答案 0 :(得分:1)
由于您知道要专门查找ID值为<div>
的{{1}}元素,因此应使用更具体的xpath查询来查找它。我希望您的“尝试2”执行立即通过,因为WebDriver位于页面的第四个appian-working-indicator-hidden
上,而这可能不是您要查找的<div>
。
您可以查询具有特定ID值using the contains()
xpath function的div#appian-working-indicator-hidden
。
您可能会重写“尝试2”,使其看起来像这样:
<div>
答案 1 :(得分:1)
您可以获取该Web元素的列表,当该元素在页面上可见时,列表的大小将为1,而当该元素不可见时,列表的大小将为0。因此,您可以检查检查它是否可见的元素。
我正在为您的元素使用相对xpath而不是您正在使用的绝对xpath,因为绝对xpath非常易变,并且html结构中的任何细微更改都可能对脚本产生影响。
您的代码应类似于:
List<WebElement> progressBarList = driver.findElements(By.xpath("//div[@id='appian-working-indicator-hidden']"));
if(progressBarList.size()>0){
System.out.println("Element is present");
}
else{
System.out.println("Element is not present");
}
答案 2 :(得分:1)
为此,我使用纯 JS 以便我可以逃避 Selenium 中的内置等待。当涉及到 Selenium 时,否定查找一直是一个大问题
Supplier<Boolean> isLoadingCheck = () -> (Boolean) js.executeScript(
"return (document.getElementById('nprogress') != null || document.getElementsByClassName('spinner').length > 0)"
);
答案 3 :(得分:0)
你使用的逻辑很好。为了防止时间溢出,您可以覆盖第二个方法调用的隐式等待时间,并将其重置为 finally 块中的原始值。 我认为当它在停止时隐式搜索进度条时,时间会流逝。