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 unfortunatelyclick_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, andpage_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.