Wait until page is loaded with Selenium WebDriver for Python

Wait until page is loaded with Selenium WebDriver for Python

The webdriver will wait for a page to load by default via .get() method.

As you may be looking for some specific element as @user227215 said, you should use WebDriverWait to wait for an element located in your page:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException

browser = webdriver.Firefox()
browser.get(url)
delay = 3 # seconds
try:
    myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, IdOfMyElement)))
    print Page is ready!
except TimeoutException:
    print Loading took too much time!

I have used it for checking alerts. You can use any other type methods to find the locator.

EDIT 1:

I should mention that the webdriver will wait for a page to load by default. It does not wait for loading inside frames or for ajax requests. It means when you use .get(url), your browser will wait until the page is completely loaded and then go to the next command in the code. But when you are posting an ajax request, webdriver does not wait and its your responsibility to wait an appropriate amount of time for the page or a part of page to load; so there is a module named expected_conditions.

Trying to pass find_element_by_id to the constructor for presence_of_element_located (as shown in the accepted answer) caused NoSuchElementException to be raised. I had to use the syntax in fragles comment:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get(url)
timeout = 5
try:
    element_present = EC.presence_of_element_located((By.ID, element_id))
    WebDriverWait(driver, timeout).until(element_present)
except TimeoutException:
    print Timed out waiting for page to load

This matches the example in the documentation. Here is a link to the documentation for By.

Wait until page is loaded with Selenium WebDriver for Python

Find below 3 methods:

readyState

Checking page readyState (not reliable):

def page_has_loaded(self):
    self.log.info(Checking if {} page is loaded..format(self.driver.current_url))
    page_state = self.driver.execute_script(return document.readyState;)
    return page_state == complete

The wait_for helper function is good, but unfortunately click_through_to_new_page is open to the race condition where we manage to execute the script in the old page, before the browser has started processing the click, and page_has_loaded just returns true straight away.

id

Comparing new page ids with the old one:

def page_has_loaded_id(self):
    self.log.info(Checking if {} page is loaded..format(self.driver.current_url))
    try:
        new_page = browser.find_element_by_tag_name(html)
        return new_page.id != old_page.id
    except NoSuchElementException:
        return False

Its possible that comparing ids is not as effective as waiting for stale reference exceptions.

staleness_of

Using staleness_of method:

@contextlib.contextmanager
def wait_for_page_load(self, timeout=10):
    self.log.debug(Waiting for page to load at {}..format(self.driver.current_url))
    old_page = self.find_element_by_tag_name(html)
    yield
    WebDriverWait(self, timeout).until(staleness_of(old_page))

For more details, check Harrys blog.

Leave a Reply

Your email address will not be published. Required fields are marked *