等待 Selenium 中的页面加载

发布于 2024-11-04 09:31:47 字数 115 浏览 5 评论 0原文

如何让 Selenium 2.0 等待页面加载?

How do you make Selenium 2.0 wait for the page to load?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

貪欢 2024-11-11 09:31:47

您还可以使用以下代码检查页面加载情况

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"));

You can also check pageloaded using following code

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"));
熟人话多 2024-11-11 09:31:47

使用类 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")));

Use class WebDriverWait

Also see here

You can expect to show some element. something like in 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")));
如何视而不见 2024-11-11 09:31:47

如果您设置驱动程序的隐式等待,然后对您期望在加载页面上的元素调用 findElement 方法,WebDriver 将轮询该元素,直到找到该元素或达到时间出值。

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

来源: 隐式等待

If you set the implicit wait of the driver, then call the findElement method on an element you expect to be on the loaded page, the WebDriver will poll for that element until it finds the element or reaches the time out value.

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

source: implicit-waits

找个人就嫁了吧 2024-11-11 09:31:47

一般来说,对于 Selenium 2.0,Web 驱动程序只有在确定页面已加载后才应将控制权返回给调用代码。如果没有,您可以调用waitforelemement,它会循环调用findelement,直到找到或超时(可以设置超时)。

In general, with Selenium 2.0 the web driver should only return control to the calling code once it has determined that the page has loaded. If it does not, you can call waitforelemement, which cycles round calling findelement until it is found or times out (time out can be set).

红ご颜醉 2024-11-11 09:31:47

红宝石实现:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}

Ruby implementation:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}
此生挚爱伱 2024-11-11 09:31:47

所有这些解决方案都适用于特定情况,但它们至少会遇到以下几个可能问题之一:

  1. 它们不够通用 - 它们希望您提前知道某些特定条件将是您将要访问的页面是否为真(例如,将显示某些元素)

  2. 它们对竞争条件开放,其中您使用了实际存在于旧页面和新页面上的元素。

这是我尝试的避免此问题的通用解决方案(在 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 号,包括顶级 元素。当页面刷新或加载时,它会获得一个带有新 ID 的新 html 元素。

因此,假设您想单击带有文本“我的链接”的链接,例如:

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)

对于更多 Pythonic、可重用、通用帮助器,您可以创建一个上下文管理器:

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)

然后您可以在几乎任何硒交互中使用它:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

我认为那是防弹的!你怎么认为?

更多信息请参见 关于它的博客文章在这里

All of these solutions are OK for specific cases, but they suffer from at least one of a couple of possible problems:

  1. They are not generic enough -- they want you to know, ahead of time, that some specific condition will be true of the page you are going to (eg some element will be displayed)

  2. They are open to a race condition where you use an element that is actually present on the old page as well as the new page.

Here's my attempt at a generic solution that avoids this problem (in Python):

First, a generic "wait" function (use a WebDriverWait if you like, I find them ugly):

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__))

Next, the solution relies on the fact that selenium records an (internal) id-number for all elements on a page, including the top-level <html> element. When a page refreshes or loads, it gets a new html element with a new ID.

So, assuming you want to click on a link with text "my link" for example:

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)

For more Pythonic, reusable, generic helper, you can make a 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)

And then you can use it on pretty much any selenium interaction:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

I reckon that's bulletproof! What do you think?

More info in a blog post about it here

夜司空 2024-11-11 09:31:47

您可以删除 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");
        }
    });
}

You may remove the System.out line. It is added for debug purposes.

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");
        }
    });
}
感性不性感 2024-11-11 09:31:47

以下是当前得票最多的答案的 Java 8 版本:

WebDriverWait wait = new WebDriverWait(myDriver, Duration.ofSeconds(15));
wait.until(webDriver -> "complete".equals(((JavascriptExecutor) webDriver)
    .executeScript("return document.readyState")));
    

其中 myDriverWebDriver 对象(之前声明)。

注意:请注意,此方法 (document.readyState) 仅检查 DOM。

Here is a Java 8 version of the currently most upvoted answer:

WebDriverWait wait = new WebDriverWait(myDriver, Duration.ofSeconds(15));
wait.until(webDriver -> "complete".equals(((JavascriptExecutor) webDriver)
    .executeScript("return document.readyState")));
    

Where myDriver is a WebDriver object (declared earlier).

Note: Be aware that this method (document.readyState) only checks the DOM.

时光礼记 2024-11-11 09:31:47

您还可以使用类:ExpectedConditions 显式等待元素显示在网页上,然后才能采取任何进一步操作

您可以使用 ExpectedConditions 类来确定元素是否可见:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

请参阅 ExpectedConditions class Javadoc 以获取您可以检查的所有条件的列表。

You can also use the class: ExpectedConditions to explicitly wait for an element to show up on the webpage before you can take any action further actions

You can use the ExpectedConditions class to determine if an element is visible:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

See ExpectedConditions class Javadoc for list of all conditions you are able to check.

花间憩 2024-11-11 09:31:47

Imran 的答案针对 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");
        }
    });

Imran's answer rehashed for 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");
        }
    });
把时间冻结 2024-11-11 09:31:47

这似乎是 WebDriver 的一个严重限制。显然,等待元素并不意味着页面正在加载,特别是 DOM 可以完全构建(onready 状态),其中 JS 仍在执行,CSS 和图像仍在加载。

我相信最简单的解决方案是在一切都初始化后在 onload 事件上设置一个 JS 变量,并在 Selenium 中检查并等待这个 JS 变量。

This seems to be a serious limitation of WebDriver. Obviously waiting for an element will not imply the page being loaded, in particular the DOM can be fully build (onready state) whereby JS is still executing and CSS and images are still loading.

I believe the simplest solution is to set a JS variable upon the onload event after everything is initialized and check and wait for this JS variable in Selenium.

彩虹直至黑白 2024-11-11 09:31:47

伙计,所有这些答案都需要太多代码。这应该是一件简单的事情,因为它很常见。

为什么不直接使用 webdriver 注入一些简单的 Javascript 并进行检查。
这是我在网络爬虫类中使用的方法。即使您不了解,Javascript 也非常基础。

def js_get_page_state(self):
"""
Javascript for getting document.readyState
:return: Pages state. See doc link below.
"""
ready_state = self.driver.execute_script('return document.readyState')
if ready_state == 'loading':
    self.logger.info("Loading Page...")
elif ready_state == 'interactive':
    self.logger.info("Page is interactive")
elif ready_state == 'complete':
    self.logger.info("The page is fully loaded!")
return ready_state

更多信息请参见 MDN Web 文档的“Document.readyState”:https ://developer.mozilla.org/en-US/docs/Web/API/Document/readyState

Man all these answers require too much code. This should be a simple thing as its pretty common.

Why not just inject some simple Javascript with the webdriver and check.
This is the method I use in my webscraper class. The Javascript is pretty basic even if you don't know it.

def js_get_page_state(self):
"""
Javascript for getting document.readyState
:return: Pages state. See doc link below.
"""
ready_state = self.driver.execute_script('return document.readyState')
if ready_state == 'loading':
    self.logger.info("Loading Page...")
elif ready_state == 'interactive':
    self.logger.info("Page is interactive")
elif ready_state == 'complete':
    self.logger.info("The page is fully loaded!")
return ready_state

More Info in "Document.readyState" of MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState

寂寞陪衬 2024-11-11 09:31:47

如果您想等待特定元素加载,可以在 RenderedWebElement 上使用 isDisplayed() 方法:(

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

示例来自 5 分钟入门指南

If you want to wait for a specific element to load, you can use the isDisplayed() method on a RenderedWebElement :

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

(Example from The 5 Minute Getting Started Guide)

滥情哥ㄟ 2024-11-11 09:31:47

在此等待中显式等待或有条件等待,直到给定此条件。

WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

这将等待每个 Web 元素 60 秒。

使用隐式等待等待页面上的每个元素直到给定时间。

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

这将等待每个 Web 元素 60 秒。

Explicitly wait or conditional wait in this wait until given this condition.

WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

This will wait for every web element for 60 seconds.

Use implicitly wait for wait of every element on page till that given time.

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

This will wait for every web element for 60 seconds.

救赎№ 2024-11-11 09:31:47

令我惊讶的是,谓词并不是首选,因为您通常知道接下来将在等待加载的页面上与哪些元素进行交互。我的方法一直是构建诸如 waitForElementByID(String id)waitForElemetVisibleByClass(String className) 等谓词/函数,然后在需要的地方使用和重用它们,无论是页面加载还是页面内容更改,我都在等待。

例如,

在我的测试类中:

driverWait.until(textIsPresent("expectedText");

在我的测试类父类中:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

虽然这看起来很多,但它会为您重复检查
并且检查频率的间隔可以与最终值一起设置
超时之前等待时间。此外,您还将重用此类方法。

在此示例中,父类定义并启动了 WebDriver 驱动程序WebDriverWait driverWait

我希望这有帮助。

I'm surprised that predicates weren't the first choice as you typically know what element(s) you will next interact with on the page you're waiting to load. My approach has always been to build out predicates/functions like waitForElementByID(String id) and waitForElemetVisibleByClass(String className), etc. and then use and reuse these wherever I need them, be it for a page load or page content change I'm waiting on.

For example,

In my test class:

driverWait.until(textIsPresent("expectedText");

In my test class parent:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

Though this seems like a lot, it takes care of checking repeatedly for you
and the interval for how often to check can be set along with the ultimate
wait time before timing out. Also, you will reuse such methods.

In this example, the parent class defined and initiated the WebDriver driver and the WebDriverWait driverWait.

I hope this helps.

千里故人稀 2024-11-11 09:31:47

使用隐式等待等待页面上的每个元素直到给定时间。

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

这会等待页面上的每个元素 30 秒。

另一种等待是显式等待或条件等待,这种等待直到给定条件。

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

在 id 中给出静态元素 id,一旦页面加载,它就会在页面上显示。

Use implicitly wait for wait of every element on page till given time.

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

this wait for every element on page for 30 sec.

Another wait is Explicitly wait or conditional wait in this wait until given condition.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

In id give static element id which is diffidently display on the page, as soon as page is load.

眼眸 2024-11-11 09:31:47

使用 WebDriver 的 Java 绑定时等待页面加载的最佳方法是将页面对象设计模式与 PageFactory 结合使用。这允许您利用 AjaxElementLocatorFactory ,简单来说,它充当所有元素的全局等待。它对下拉框或复杂的 JavaScript 转换等元素有限制,但它将大大减少所需的代码量并加快测试时间。这篇博文中有一个很好的例子。假定您对 Core Java 有基本的了解。

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait -in-page-factory.html

The best way to wait for page loads when using the Java bindings for WebDriver is to use the Page Object design pattern with PageFactory. This allows you to utilize the AjaxElementLocatorFactory which to put it simply acts as a global wait for all of your elements. It has limitations on elements such as drop-boxes or complex javascript transitions but it will drastically reduce the amount of code needed and speed up test times. A good example can be found in this blogpost. Basic understanding of Core Java is assumed.

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html

等你爱我 2024-11-11 09:31:47

在脚本中调用下面的函数,这将等到页面未使用 javascript 加载

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}

Call below Function in your script , this will wait till page is not loaded using javascript

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
半暖夏伤 2024-11-11 09:31:47

NodeJS解决方案:

Nodejs中,你可以通过promise来获取它...

如果你编写这段代码,你可以确保当你到达then时页面已完全加载...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

如果您编写此代码,您将进行导航,selenium 将等待 3 秒...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

Selenium 文档 (Nodejs)

this.get( url ) → Thenable;

安排命令导航到给定的 URL。

返回一个承诺,该承诺将在文档完成加载时解决。

NodeJS Solution:

In Nodejs you can get it via promises...

If you write this code, you can be sure that the page is fully loaded when you get to the then...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

If you write this code, you will navigate, and selenium will wait 3 seconds...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

From Selenium Documentation (Nodejs):

this.get( url ) → Thenable<undefined>

Schedules a command to navigate to the given URL.

Returns a promise that will be resolved when the document has finished loading.

野味少女 2024-11-11 09:31:47

您可以使用以下现有方法来设置pageLoadTimeout。在下面的示例中,如果页面加载时间超过 20 秒,则会抛出页面重新加载异常:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);

You can use the below existing method to set the pageLoadTimeout. In below example if the page is taking more than 20 seconds to load, then it will throw an exception of page reload:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
吃不饱 2024-11-11 09:31:47
/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

在仅更改文档的一部分的情况下,您可以从文档更改为元素。

这项技术的灵感来自于sincebasic的答案。

/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

You can change from the document to an element, in the case of where only part of a document is being changed.

This technique was inspired by the answer from sincebasic.

别想她 2024-11-11 09:31:47

SeleniumWaiter

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

使用它

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}

SeleniumWaiter:

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

And to you use it:

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}
烟酉 2024-11-11 09:31:47

您可以显式等待元素显示在网页上,然后才能执行任何操作(例如 element.click()):

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
    .until(new ExpectedCondition<WebElement>() {
        @Override
        public WebElement apply(WebDriver d) {
            return d.findElement(By.id("myDynamicElement"));
        }
    }
);

这是我在类似场景中使用的方法,效果很好。

You can explicitly wait for an element to show up on the webpage before you can take any action (like element.click()):

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
    .until(new ExpectedCondition<WebElement>() {
        @Override
        public WebElement apply(WebDriver d) {
            return d.findElement(By.id("myDynamicElement"));
        }
    }
);

This is what I used for a similar scenario and it works fine.

穿透光 2024-11-11 09:31:47

我的简单方法:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }

My simple way:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }
情深缘浅 2024-11-11 09:31:47

您可以使用这段代码来加载页面:

    IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00));
    wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

或者您可以使用 waiter 来加载任何元素,并在该页面上变得可见/可点击,很可能会在加载结束时加载,例如:

    Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement));
    var element = GlobalDriver.FindElement(By.XPath(xpathOfElement));
    var isSucceededed = element != null;

You can use this snippet of code for the page to load:

    IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00));
    wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

Or you can use waiter for any element to be loaded and become visible/clickable on that page, most probably which is going to be load at the end of loading like:

    Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement));
    var element = GlobalDriver.FindElement(By.XPath(xpathOfElement));
    var isSucceededed = element != null;
寻找一个思念的角度 2024-11-11 09:31:47

我见过的最好的方法是利用 stalenessOf ExpectedCondition,等待旧页面变得过时。

示例:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

它将等待十秒钟,让旧的 HTML 标记变得过时,如果没有发生,则抛出异常。

The best way I've seen is to utilize the stalenessOf ExpectedCondition, to wait for the old page to become stale.

Example:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

It'll wait for ten seconds for the old HTML tag to become stale, and then throw an exception if it doesn't happen.

哽咽笑 2024-11-11 09:31:47

我使用node + selenium-webdriver(现在版本是3.5.0)。我为此所做的是:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))

I use node + selenium-webdriver(which version is 3.5.0 now). what I do for this is:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))
情丝乱 2024-11-11 09:31:47

您可以使用等待。 selenium 中基本上有 2 种类型的等待

  • 隐式等待
  • 显式等待

- 隐式等待

这非常简单,请参阅下面的语法:

driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

- 显式等待

在这种等待中显式等待或条件等待直到给定的条件发生。

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

您可以使用其他属性,例如 visbityOf()visbityOfElement()

You can use wait. there are basically 2 types of wait in selenium

  • Implicit wait
  • Explicit wait

- Implicit wait

This is very simple please see syntax below:

driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

- Explicit wait

Explicitly wait or conditional wait in this wait until given condition is occurred.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

You can use other properties like visblityOf(), visblityOfElement()

半枫 2024-11-11 09:31:47

如果有人使用硒化物:

public static final Long SHORT_WAIT = 5000L; // 5 seconds
$("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);

可以在此处找到更多条件:
http://selenide.org/javadoc/3.0/com/codeborne/硒化物/Condition.html

If someone uses selenide:

public static final Long SHORT_WAIT = 5000L; // 5 seconds
$("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);

More Conditions can be found here:
http://selenide.org/javadoc/3.0/com/codeborne/selenide/Condition.html

伴随着你 2024-11-11 09:31:47

就我而言,我使用以下方法来了解页面加载状态。在我们的应用程序中,存在加载 gif,我按如下方式收听它们,以消除脚本中不必要的等待时间。

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

xpath 在 HTML DOM 中定位 gif 的位置。
之后,您还可以实现您的操作方法 Click。

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }

In my case , I used the following to know the page load status. In our application loading gif(s) are present and, I listen to them as follows to eliminate unwanted wait time in the script.

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

Where the xpath locates the gif in the HTML DOM.
After this, You may also implement your action methods Click.

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文