Đợi tải trang trong Selenium


Câu trả lời:


138

Bạn cũng có thể kiểm tra tải bằng cách sử dụng mã sau

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

22
Bạn sẽ nghĩ một cái gì đó như thế này sẽ được tích hợp. Chờ tải trang là một điều khá phổ biến trên web.
PRman

19
điều này thực sự làm việc tất cả các thời gian? Có thể tôi đang thiếu một cái gì đó từ mã của bạn nhưng bạn đang chờ đợi dom ở trạng thái sẵn sàng. Nhưng hãy xem xét rằng nếu mã của bạn thực thi quá nhanh, trang trước đó có thể chưa được tải và nó sẽ trả về đúng mặc dù bạn vẫn ở trang cũ. Những gì bạn cần làm là đợi trang hiện tại dỡ xuống và sau đó gọi mã trên của bạn. Một cách để phát hiện việc dỡ trang là lấy một trang web trên trang hiện tại và đợi cho đến khi nó trở nên cũ. obeythetestinggoat.com/ từ
George

6
FYI - Ngay cả những điều trên vẫn không đảm bảo rằng trang đã hoàn tất - chỉ là dom đã sẵn sàng. Bất kỳ dojo / jquery nào vẫn có thể tự động xây dựng các yếu tố trên trang, do đó bạn có thể cần đợi phần tử động trước khi tương tác với chúng.
George

3
Xin lưu ý rằng phương pháp này chỉ kiểm tra DOM. Nếu bạn sử dụng Ajax hoặc AngularJS, điều này sẽ không hoạt động vì sẽ có một số cuộc gọi không đồng bộ không thể được phát hiện bởi tài liệu. YetState.
Homewrecker

3
Đây là mã C #. Điều này không hoạt động với Java và câu hỏi được hỏi về Java .
Kingamere

89

Sử dụng lớp WebDriverWait

Cũng xem tại đây

Bạn có thể mong đợi để hiển thị một số yếu tố. một cái gì đó giống như trong 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"));

Điều này đã làm việc tuyệt vời. Đó là một cách hiện đại rất tốt đẹp để giải quyết vấn đề.
CrazyDart

3
@ EmmanuelAngelo.R TimeSpan là cấu trúc dữ liệu .Net.
rjzii

12
Điều gì xảy ra nếu tôi không biết yếu tố nào sẽ xuất hiện trên trang?
JustGoscha

3
Điều này sẽ hoạt động để chờ tải một phần tử cụ thể chứ không phải cho toàn bộ trang.
xyz

1
Điều này không đảm bảo rằng một phần tử sẽ được tải đầy đủ cũng không trả lời câu hỏi. Làm thế nào bất cứ ai có thể nâng cao điều này?
Boris D. Teoharov

36

Nếu bạn đặt chờ đợi ngầm định của trình điều khiển, sau đó gọi findElementphương thức trên một phần tử mà bạn mong đợi sẽ ở trên trang được tải, WebDriver sẽ thăm dò phần tử đó cho đến khi tìm thấy phần tử hoặc đạt đến giá trị hết thời gian.

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

nguồn: ngầm-chờ đợi


3
Nó sẽ không giúp đỡ trong việc chờ tải trang.
xyz

Nó có nghĩa là nó sẽ thử một cái gì đó trong 10 giây, trước khi nó đưa ra ngoại lệ. vì vậy nó không thể đảm bảo rằng nó sẽ mất 10 giây.
skysign

1
@xyz - tại sao nó không giúp được?
MasterJoe2

@ testsjoe2 nó đợi cho đến khi tìm thấy phần tử cụ thể, câu hỏi là về cách chờ tải trang.
xyz

35

Nói chung, với Selenium 2.0, trình điều khiển web chỉ nên trả lại quyền điều khiển cho mã cuộc gọi khi nó đã xác định rằng trang đã được tải. Nếu không, bạn có thể gọi waitforelemement, sẽ quay vòng cuộc gọi findelementcho đến khi tìm thấy hoặc hết thời gian (có thể đặt thời gian chờ).


2
Thêm vào câu trả lời của Paul. Vui lòng kiểm tra điều này cũng stackoverflow.com/questions/5858743/ .
9ikhan

27
Thật không may, Selenium 2 không chờ trong mọi trường hợp để tải trang. Ví dụ: WebE bổ sung: click () không chờ đợi và điều này được nói rõ ràng trong Javadoc thuộc. Tuy nhiên, họ không cho biết làm thế nào tôi có thể kiểm tra một trang mới sẽ được tải. If click() causes a new page to be loaded via an event or is done by sending a native event (which is a common case on Firefox, IE on Windows) then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
Sebi

Từ doc .. và phương thức sẽ chặn cho đến khi tải xong ...
xyz

2
@Karna: Vâng, về lý thuyết, nó luôn luôn như vậy và trong thực tế, nó đã làm hầu hết thời gian. Sử dụng Selenium tại thời điểm đó nhấn mạnh rằng có những lúc nó nghĩ rằng trang đã tải xong nhưng không được. Gần đây tôi không sử dụng selenium nên điều này có thể hoặc không thể vẫn như vậy.
Paul Hadfield

3
Tôi đồng ý: đặc biệt là trình điều khiển trình thám hiểm internet bị lỗi và trả lại quyền kiểm soát ngay lập tức trong một số trường hợp mặc dù một trang vẫn đang tải. Đó là trường hợp của tôi, tôi đã thêm một sự chờ đợi bằng cách sử dụng JavascriptExecutor, chờ đợi tài liệu. YetState sẽ "hoàn tất". Bởi vì chuyến đi khứ hồi từ selenium đến trình duyệt, điều kiện cuộc đua được giảm nhẹ tôi đoán, và điều này "luôn luôn" hoạt động với tôi. Sau khi "click ()" khi tôi mong đợi một trang sẽ tải, tôi rõ ràng chờ đợi (sử dụng WebDriverWait) để đọc. ]
dmansfield

22

Thực hiện Ruby:

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

17
Tương đương với Python: WebDriverWait (trình điều khiển, 10) .until (lambda d: d.execute_script ('return document. YetState') == 'hoàn thành')
blaze

2
Python sử dụng đoạn mã trên nhưng đừng quên dòng này .. | từ selenium.webdo.support.ui nhập WebDriverWait
t3dodson

Tôi gặp sự cố khi nhấp vào một yếu tố khi trang chưa được tải đầy đủ. Trong Python tôi đã thử time.s ngủ (30). Nó đã làm việc. Nó sẽ luôn chờ tối đa 30 giây. Sau đó tôi đã thử đoạn mã sau và nó hiệu quả hơn bây giờ, nhanh hơn. WebDriverWait (trình điều khiển, 10) .until (lambda d: driver.find_element_by_xpath ("// div [. = 'Quản trị']"). Click ())
Riaz Ladhani

20

Bạn có thể loại bỏ các System.outdòng. Nó được thêm vào cho mục đích gỡ lỗi.

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

Cảm ơn lời khuyên này. Tôi thêm nó vào SeleniumHelper của tôi; xem javabox
boly38

17

Tất cả các giải pháp này đều ổn đối với các trường hợp cụ thể, nhưng chúng gặp phải ít nhất một trong một vài vấn đề có thể xảy ra:

  1. Chúng không đủ chung chung - họ muốn bạn biết trước thời hạn, một số điều kiện cụ thể sẽ đúng với trang bạn sẽ đến (ví dụ: một số yếu tố sẽ được hiển thị)

  2. Chúng được mở cho một điều kiện cuộc đua trong đó bạn sử dụng một yếu tố thực sự có mặt trên trang cũ cũng như trang mới.

Đây là nỗ lực của tôi tại một giải pháp chung tránh được vấn đề này (bằng Python):

Đầu tiên, một chức năng "chờ" chung (sử dụng WebDriverWait nếu bạn thích, tôi thấy chúng xấu xí):

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

Tiếp theo, giải pháp dựa trên thực tế là selen ghi lại số id (nội bộ) cho tất cả các thành phần trên một trang, bao gồm cả thành <html>phần cấp cao nhất. Khi một trang làm mới hoặc tải, nó nhận được một phần tử html mới với ID mới.

Vì vậy, giả sử bạn muốn nhấp vào liên kết có văn bản "liên kết của tôi" chẳng hạn:

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)

Để có thêm trình trợ giúp chung, có thể tái sử dụng, Pythonic, bạn có thể tạo trình quản lý bối cảnh:

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)

Và sau đó bạn có thể sử dụng nó trên hầu hết mọi tương tác selen:

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

Tôi nghĩ đó là chống đạn! Bạn nghĩ sao?

Thông tin thêm trong một bài đăng blog về nó ở đây


Tôi đọc trang web của bạn trước khi tìm kiếm lại cụ thể hơn cho mã java thực hiện giải pháp của bạn. Không có gì cho đến nay ...
rút lorien

11

Bạn cũng có thể sử dụng lớp: ExpectedConditionsđể chờ một phần tử hiển thị trên trang web một cách rõ ràng trước khi bạn có thể thực hiện bất kỳ hành động nào khác

Bạn có thể sử dụng ExpectedConditionslớp để xác định xem một phần tử có thể nhìn thấy hay không:

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

Xem ExpectedConditions class Javadocđể biết danh sách tất cả các điều kiện bạn có thể kiểm tra.


11

Câu trả lời của Imran đã được thử lại cho 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");
        }
    });

10

Đây dường như là một hạn chế nghiêm trọng của WebDriver. Rõ ràng việc chờ đợi một phần tử sẽ không ngụ ý trang đang được tải, đặc biệt là DOM có thể được xây dựng hoàn chỉnh (trạng thái sẵn sàng), theo đó, JS vẫn đang thực thi và CSS và hình ảnh vẫn đang tải.

Tôi tin rằng giải pháp đơn giản nhất là đặt biến JS theo sự kiện onload sau khi mọi thứ được khởi tạo và kiểm tra và chờ đợi biến JS này trong Selenium.


Thật đơn giản nếu trang web là của bạn để sửa đổi!
Revierpost

Đúng, chỉ cần sử dụng JavascriptExecutor để thực thi jQuery.js và sau đó bạn có quyền truy cập vào các sự kiện tải jQuery. Đó là một trường hợp hiếm hoi khi điều này là cần thiết mặc dù. Webdo tiêu chuẩn có đủ sức mạnh để thực hiện 98% sự chờ đợi thích hợp.
djangofan

@djangofan sẽ thật tuyệt vời khi xem một ví dụ về điều đó ... Tôi là một người đi trước nên không chắc chắn JavascriptExecutor được sử dụng ở đâu và như thế nào.
BradGreen

@BradGreen - Ok, hãy xem dự án của tôi ở đây: github.com/djangofan/jquery-growl-selenium-example . Nếu bạn có băng thông để hoàn thành ví dụ đó, tôi hoàn toàn không thể làm cho jGrowl hoạt động trong dự án thử nghiệm đó, mặc dù jQuery hoạt động tốt.
djangofan

1
@BradGreen Ngoài nhận xét của djangofan, hãy xem câu trả lời của tôi ở đây: stackoverflow.com/a/24638792/730326
jmathew

9

Nếu bạn muốn đợi một phần tử cụ thể tải, bạn có thể sử dụng isDisplayed()phương thức trên 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;
    }
}

(Ví dụ từ Hướng dẫn bắt đầu 5 phút )


4
Một năm sau (phiên bản Selenium hiện tại 2.23.1), không có RenderedWebElementAPI. Tuy nhiên, isDisplayed()phương pháp hiện có sẵn trực tiếp trên WebElement.
Petr Janeček

1
Bỏ phiếu là khủng khiếp khi nó có thể tránh được.
Revierpost

8

Hoàn toàn chờ đợi hoặc chờ đợi có điều kiện trong chờ đợi này cho đến khi đưa ra điều kiện này.

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

Điều này sẽ chờ cho mọi yếu tố web trong 60 giây.

Sử dụng ngầm chờ đợi mọi yếu tố trên trang cho đến thời điểm đó.

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

Điều này sẽ chờ cho mọi yếu tố web trong 60 giây.


5

Sử dụng ngầm chờ đợi mọi yếu tố trên trang cho đến thời gian nhất định.

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

điều này chờ cho mọi phần tử trên trang trong 30 giây.

Một sự chờ đợi khác là chờ đợi một cách rõ ràng hoặc chờ đợi có điều kiện trong sự chờ đợi này cho đến khi có điều kiện nhất định.

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

Trong id cung cấp id phần tử tĩnh được hiển thị rõ ràng trên trang, ngay khi trang được tải.


4

Tôi ngạc nhiên rằng các vị từ không phải là lựa chọn đầu tiên vì bạn thường biết phần tử nào bạn sẽ tương tác tiếp theo trên trang bạn đang chờ tải. Biện pháp của tôi đã luôn luôn được xây dựng ra các vị từ / chức năng như waitForElementByID(String id)waitForElemetVisibleByClass(String className), vv và sau đó sử dụng và tái sử dụng những bất cứ nơi nào tôi cần đến chúng, có thể là cho một tải trang hoặc trang thay đổi nội dung tôi đang chờ đợi trên.

Ví dụ,

Trong lớp kiểm tra của tôi:

driverWait.until(textIsPresent("expectedText");

Trong lớp kiểm tra của tôi phụ huynh:

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

Mặc dù điều này có vẻ rất nhiều, nhưng bạn cần kiểm tra nhiều lần cho bạn và khoảng thời gian kiểm tra có thể được đặt cùng với thời gian chờ cuối cùng trước khi hết thời gian. Ngoài ra, bạn sẽ sử dụng lại các phương pháp như vậy.

Trong ví dụ này, lớp cha được định nghĩa và khởi tạo WebDriver driverWebDriverWait driverWait.

Tôi hi vọng cái này giúp được.


Điều này giúp tôi! Cảm ơn cho mẫu tuyệt vời này. Tôi thêm nó vào SeleniumHelper của tôi; xem javabox
boly38

4

Cách tốt nhất để chờ tải trang khi sử dụng các liên kết Java cho WebDriver là sử dụng mẫu thiết kế Đối tượng trang với PageFactory. Điều này cho phép bạn sử dụng AjaxElementLocatorFactorycái để đặt nó đơn giản hoạt động như một sự chờ đợi toàn cầu cho tất cả các yếu tố của bạn. Nó có những hạn chế đối với các yếu tố như hộp thả hoặc chuyển đổi javascript phức tạp nhưng nó sẽ làm giảm đáng kể số lượng mã cần thiết và tăng tốc thời gian thử nghiệm. Một ví dụ tốt có thể được tìm thấy trong blogpost này. Hiểu biết cơ bản về Core Java được giả định.

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


4

Giải pháp NodeJS:

Trong Nodejs, bạn có thể nhận được thông qua lời hứa ...

Nếu bạn viết mã này, bạn có thể chắc chắn rằng trang đã được tải đầy đủ khi bạn đến ...

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

Nếu bạn viết mã này, bạn sẽ điều hướng và selen sẽ đợi 3 giây ...

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...

Từ tài liệu Selenium:

this .get (url) → Có thể

Lên lịch một lệnh để điều hướng đến URL đã cho.

Trả về một lời hứa sẽ được giải quyết khi tài liệu đã tải xong .

Tài liệu Selenium (Nodejs)


4

Đây là phiên bản Java 8 của câu trả lời được đánh giá cao nhất hiện nay :

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

Trường hợp myDriverlà một WebDriverđối tượng (khai báo trước đó).

Lưu ý : Lưu ý rằng phương thức này ( document.readyState) chỉ kiểm tra DOM.


4

Gọi bên dưới Chức năng trong tập lệnh của bạn, điều này sẽ đợi cho đến khi trang không được tải bằng javascript

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

Tôi đã thay đổi boolean thành void, nhưng không hoạt động trong Chrome
Nasqueweaponer

3
/**
 * 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;
        }
    });
}

Bạn có thể thay đổi từ tài liệu thành một yếu tố, trong trường hợp chỉ một phần của tài liệu được thay đổi.

Kỹ thuật này được lấy cảm hứng từ câu trả lời từ frombasic.


3

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

Và để bạn sử dụng nó :

_waiter = new SeleniumWaiter(_driver);

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

3

Bạn có thể sử dụng phương thức hiện có bên dưới để đặt thời gian cho pageeLoadTimeout trong ví dụ bên dưới nếu trang mất hơn 20 giây để tải, sau đó nó sẽ ném ngoại lệ tải lại trang

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

2

Bạn rõ ràng có thể đợi một phần tử hiển thị trên trang web trước khi bạn có thể thực hiện bất kỳ hành động nào (như 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"));
}});

Đây là những gì tôi đã sử dụng cho một kịch bản tương tự và nó hoạt động tốt.


tôi nghĩ driver.get đợi chức năng onload kết thúc trước khi trả lại quyền điều khiển cho mã, trừ khi trang có rất nhiều ajax
goh

2

Cách đơn giản của tôi:

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

        while (System.currentTimeMillis() < end) {

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

2

Cách tốt nhất tôi thấy là sử dụng stalenessOf ExpectedCondition, chờ trang cũ trở nên cũ.

Thí dụ:

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

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

Sẽ đợi mười giây để thẻ HTML cũ trở nên cũ và sau đó ném ngoại lệ nếu điều đó không xảy ra.


1
một trang web cũ sẽ không có nghĩa là một trang mới được tải xong.
Corey Goldberg

Chắc chắn, nhưng nó có nghĩa là trang cũ đã tải xong. Theo kinh nghiệm của tôi, điều quan trọng là phải biết khi nào trang cũ đã được tải hoặc nếu nó bị dừng vì một số lý do.
forresthopkinsa

Tất nhiên, tôi thường sử dụng stalityOf kết hợp với các thử nghiệm khác để có được quá trình tải / tải đầy đủ.
forresthopkinsa

2

Tôi sử dụng nút + selenium-webdo (phiên bản nào là 3.5.0 bây giờ). những gì tôi làm cho điều này là:

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

2

Bạn có thể sử dụng chờ đợi. về cơ bản có 2 loại chờ trong selen

  • Chờ đợi ngầm
  • Chờ đợi

- Chờ đợi ngầm

Điều này rất đơn giản xin vui lòng xem cú pháp dưới đây:

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

- Chờ đợi rõ ràng

Hoàn toàn chờ đợi hoặc chờ đợi có điều kiện trong chờ đợi này cho đến khi điều kiện được đưa ra.

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

Bạn có thể sử dụng các thuộc tính khác như visblityOf(),visblityOfElement()



2

Trong trường hợp của tôi, tôi đã sử dụng như sau để biết trạng thái tải trang. Trong ứng dụng tải gif (s) của chúng tôi có mặt và, tôi lắng nghe họ như sau để loại bỏ thời gian chờ đợi không mong muốn trong tập lệnh.

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

Trong đó xpath định vị gif trong HTML DOM. Sau này, Bạn cũng có thể thực hiện các phương thức hành động của mình Bấm.

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(); 
 }

2

Man tất cả những câu trả lời yêu cầu quá nhiều mã. Đây là một điều đơn giản vì nó khá phổ biến.

Tại sao không chỉ tiêm một số javascript đơn giản với webdo và kiểm tra. Đây là phương pháp tôi sử dụng trong lớp webscraper của mình. Các javascript khá cơ bản ngay cả khi bạn không biết js.

    def js_get_page_state(self):        
    """
    Javascript for getting document.readyState
    :return: Pages state.

    More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
    """
    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

1

Cách nhận Selenium để chờ tải trang sau khi nhấp chuột cung cấp cách tiếp cận thú vị sau:

  1. Lưu trữ một tài liệu tham khảo đến một WebElementtừ trang cũ.
  2. Nhấp vào liên kết.
  3. Tiếp tục gọi các hoạt động trên WebElementcho đến khi StaleElementReferenceExceptionđược ném.

Mã mẫu:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});

Ý tưởng tốt! Tôi chưa bao giờ nghĩ sẽ giải quyết tình huống này bằng cách kiểm tra ngược lại tải trang thành công, dỡ trang thành công (vì thiếu một thuật ngữ tốt hơn). Mặc dù đây có phải là tùy chọn tốt nhất hay không dựa trên việc StaleEuityReferenceException có mất ít thời gian hơn hay không, hơn là chờ tải thành công. Tuy nhiên, một cách tốt khác để làm điều đó.
Joseph Orlando

4
Điều này sẽ không cho bạn biết liệu trang hiện tại đã được tải hay chưa, nó sẽ cho bạn biết liệu trang cuối cùng (cụ thể là một phần tử) có được tải hay không . Bạn vẫn sẽ cần đợi trang hiện tại tải. BTW, bạn có thể thay thế mã của bạn ở trên với new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element)).
JeffC
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.