Selenium, как управлять ожиданием загрузки страницы? - PullRequest
1 голос
/ 04 февраля 2020

Я некоторое время занимаюсь разработкой веб-сканеров, и самая распространенная проблема для меня - это ожидание полной загрузки страницы, включающей запросы, фреймы, сценарии. Я имею в виду полностью готово.

Я использовал несколько методов, чтобы исправить это, но когда я использую более одного потока для сканирования сайтов, я всегда сталкиваюсь с такой проблемой. Драйвер открывается сам, просматривает URL, не ждет и переходит к следующему URL.

Мои попытки:

JavascriptExecutor js = (JavascriptExecutor) driver.getWebDriver();
String result = js.executeScript("return document.readyState").toString();
    if (!result.equals("complete")) {
         Thread.sleep(1000)
    } 
}

wait.until (ExpectedConditions.visibilityOfElementLocated (By.xpath));

Когда я запускаю однопоточный код, у меня не было проблем со страницами, но, когда я использую многопоточность, это становится кошмаром. Сеть не может обрабатывать веб-страницы, как однопоточные, поэтому мне нужно ждать в это время. Я ищу точное решение. Есть какой-нибудь слушатель прогресса или что-то в этом роде?

Я жду вашего совета.

Аналогичный вопрос:

Селен - Как ждать, пока страница не появится полностью загружен

Ответы [ 3 ]

1 голос
/ 04 февраля 2020

Ожидание, пока document.readyState будет complete, не является полностью доказательственным подходом для обеспечения присутствия , видимости или интерактивности элемента.

Следовательно, функция:

JavascriptExecutor js = (JavascriptExecutor) driver.getWebDriver();
String result = js.executeScript("return document.readyState").toString();
    if (!result.equals("complete")) {
     Thread.sleep(1000)
    } 
}

И даже ожидание jQuery.active == 0:

public void WaitForAjax2Complete() throws InterruptedException
{
    while (true)
    {
        if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
            break;
    }
    Thread.sleep(100);
    }
}

Будут чистыми накладными расходами.

Вы Вы можете найти пару соответствующих обсуждений в:


Решение

Эффективный подход заключается в том, чтобы вызвать WebDriverWait несоответствие с Ожидаемые условия либо для:

  • наличие элемента
  • видимость элемента
  • интерактивность элемента

Вы можете найти пару соответствующих обсуждений в:


Более одного поток для сканирования

WebDriver не является потокобезопасным . Сказав это, если вы можете сериализовать доступ к базовому экземпляру драйвера, вы можете поделиться ссылкой более чем в одном потоке. Это не рекомендуется. Но вы всегда можете создать один экземпляр WebDriver для каждого потока.

В идеале проблема thread-safety не в вашем коде, а в реальных привязках браузера. Все они предполагают, что будет только одна команда за раз (например, как настоящий пользователь). Но с другой стороны, вы всегда можете создать один экземпляр WebDriver для каждого потока, который будет запускать несколько вкладок просмотра / windows. До этого момента кажется, что ваша программа идеальна.

Теперь разные потоки могут быть запущены на одном и том же Webdriver , но тогда результаты тестов не будут такими вы ожидаете. Причина в том, что когда вы используете многопоточность для запуска разных тестов на разных вкладках / windows требуется немного кодирования безопасности потока, иначе действия, которые вы будете выполнять, например click() или send_keys(), будут go к открытой вкладке / окну, в котором в данный момент находится focus независимо от того, какой поток вы ожидаете запустить. По сути, это означает, что все тесты будут выполняться одновременно на одной вкладке / в окне, которое имеет focus , но , а не на предполагаемой вкладке / окне.

1 голос
/ 04 февраля 2020

В вашем коде вы проверяете readyState, и если значение не complete, вы просто sleep в течение одной секунды и переходите к следующим шагам. Вот код, который ждет 10 секунд, используя WebDriverWait. Или вы можете использовать простой для l oop:

WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(d -> ((JavascriptExecutor) d).executeScript("return document.readyState !== 'loading'"));

или с interactive

wait.until(d -> ((JavascriptExecutor) d).executeScript("return (document.readyState === 'complete' || document.readyState === 'interactive')"));
0 голосов
/ 04 февраля 2020
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")));
}`enter code here`
...