Wait until loader disappears python selenium - python

<div id="loader-mid" style="position: absolute; top: 118.5px; left: 554px; display: none;">
<div class="a">Loading</div>
<div class="b">please wait...</div>
</div>
And want to wait until it disappears. I have following code but it wait sometimes too long and at some point of code it suddenly freeze all process and I don't know why.
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
self.wait = WebDriverWait(driver, 10)
self.wait.until(EC.invisibility_of_element_located((By.XPATH, "//*[#id='loader_mid'][contains(#style, 'display: block')]")))
and also I tried this one:
self.wait.until_not(EC.presence_of_element_located((By.XPATH, "//*[#id='loader_mid'][contains(#style, 'display: block')]")))
I don't know exactly how to check but maybe my element is always present on the page and selenium thought that it is there, the only thing that changes is parameter display changes from none to block. I think I can get attribute like string and check if there is word "block" but it is so wrong I thing... Help me please.

Reiterated your answer (with some error handling) to make it easier for people to find the solution :)
Importing required classes:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
Configuration variables:
SHORT_TIMEOUT = 5 # give enough time for the loading element to appear
LONG_TIMEOUT = 30 # give enough time for loading to finish
LOADING_ELEMENT_XPATH = '//*[#id="xPath"]/xPath/To/The/Loading/Element'
Code solution:
try:
# wait for loading element to appear
# - required to prevent prematurely checking if element
# has disappeared, before it has had a chance to appear
WebDriverWait(driver, SHORT_TIMEOUT
).until(EC.presence_of_element_located((By.XPATH, LOADING_ELEMENT_XPATH)))
# then wait for the element to disappear
WebDriverWait(driver, LONG_TIMEOUT
).until_not(EC.presence_of_element_located((By.XPATH, LOADING_ELEMENT_XPATH)))
except TimeoutException:
# if timeout exception was raised - it may be safe to
# assume loading has finished, however this may not
# always be the case, use with caution, otherwise handle
# appropriately.
pass

Use expected condition : invisibility_of_element_located
This works fine for me.
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait(driver, timeout).until(EC.invisibility_of_element_located((By.ID, "loader-mid")))

The following code creates an infinite loop until the element disappears:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
while True:
try:
WebDriverWait(driver, 1).until(EC.presence_of_element_located((By.XPATH, 'your_xpath')))
except TimeoutException:
break

Ok, here is how i solved this issue for my project,
imports
from selenium.common.exceptions import TimeoutException
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait as wait
Now the code part
browser = webdriver.Chrome(service=Service("./chromedriver.exe"))
browser.get("https://dashboard.hcaptcha.com/signup?type=accessibility")
try:
d = wait(browser, 10).until(EC.invisibility_of_element_located((By.ID, 'loader-mid')))
if d: # just a check you can ignore it.
print("yes")
sleep(3)
else:
print("F")
except TimeoutException:
print("timeout error occurred.")
pass
browser.quit()
Or you can use Implicit wait
driver.implicitly_wait(10) # seconds
# do something after...

Related

How to check if an element is not displayed in selenium python

How could I check to see if an element is not displayed. I would think it looks something like this.
if(element.is_not_displayed):
doSomething()
else
doSomethingElse()
To start with, there is no is_not_displayed attribute in Selenium.
To simulate a similar logic, instead of an if-else loop you may use a try-except{} loop inducing WebDriverWait for the invisibility_of_element() and you can use the following Locator Strategy:
try:
WebDriverWait(driver, 30).until(EC.invisibility_of_element(element))
doSomething()
except TimeoutException:
doSomethingElse()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
You have to use until_not as shown bellow
WebDriverWait(driver, "time you want to wait".until_not(EC.presence_of_element_located((By.ID,"someID")))
Example:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID,"transpdiv-0"))) #here yout wait to the element appear
WebDriverWait(driver, 300).until_not(EC.presence_of_element_located((By.ID,"transpdiv-0"))) #here you wait the element disappear
Note: you have to add the same imports like undetect Selenium says:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

Message: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]"}

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
import time
print('\n')
print("PROGRAM STARTING")
print('~~~~~~')
print('\n')
# initiate driver
driver = webdriver.Chrome()
driver.get('http://arcselfservice.sbcounty.gov/web/user/disclaimer')
#begin
driver.find_element_by_xpath('//*[#id="submitDisclaimerAccept"]').click()
driver.find_element_by_xpath('/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]').click()
I have been stuck on this error for a long time, for some reason it can't find the element even though I am specifying the xpath. There doesn't seem to be any iframes, and implicit or explicit wait doesn't work either. Please help.
So the issue was waiting for the element to come up and then clicking it.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]"))).click()
Another way if you want to change to the other tags later.
path = "//a/div/h1[text()='{}']/../..".format("Fictitious Business Names Application")
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH ,path))).click()
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
The error is coming because the element is taking time to be available for use. Kindly use the explicit wait for the element extraction.
A small snippet can be:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH ,'/html/body/div[2]/div[2]/div/div[3]/div[2]/div/div/div[2]/a[1]'))).click()
Just dont forget to import
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

How do i make explicit wait check for page source

This is just an example, but I want if Hello in html source on explicit wait, how do I make it work?
if "Hello" in html_source:
WebDriverWait wait = new WebDriverWait(driver,10)
wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("foobar")))
From selenium documentation
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//*[text()='Hello']")))
print(driver.page_source)
except:
print("element could not be found within the 10 second timeout period")
If you want a better answer, I suggest you ask a better question and use examples.

Unable to make my script wait conditionally

I've tried to write a script in python in combination with selenium to wait for a certain element to be available. The content I wish my script waits for is captcha protected. I do not want to set a fixed time. So, I need it to wait until I can solve myself.
I've tried like:
import time
from selenium import webdriver
URL = "https://www.someurl.com/"
driver = webdriver.Chrome()
driver.get(URL)
while not driver.find_element_by_css_selector(".listing-content"):
time.sleep(1)
print(driver.current_url)
driver.quit()
But, the script throws an error:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:
How can I make my script wait until the element is available no matter how long it takes?
If you don't want to hardcode wait time you can use ExplicitWait along with float("inf") which in Python stands for INFINITY:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support import expected_conditions as EC
wait(driver, float("inf")).until(EC.presence_of_element_located((By.CLASS_NAME, "listing-content")))
As you've asked how to organize the try/except block, here is an idea. I would suggest to stick with the inf-wait method however.
while True:
try:
driver.find_element_by_css_selector(".listing-content")
break
except:
time.sleep(0.1)
I would include the time.sleep() statement to minimize your number of function calls.
You should use WebDriverWait:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
element = WebDriverWait(driver, 10000).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".listing-content")))
It will not wait indefinitely, but you can set the timeout high. Otherwise you could try to use the WebDriverWait statement in a loop.

What is the best way to check URL change with Selenium in Python?

So, what's I want to do is to run a function on a specific webpage (which is a match with my regex).
Right now I'm checking it every second and it works, but I'm sure that there is a better way (as it's flooding that website with getting requests).
while flag:
time.sleep(1)
print(driver.current_url)
if driver.current_url == "mydesiredURL_by_Regex":
time.sleep(1)
myfunction()
I was thinking to do that somehow with WebDriverWait but not really sure how.
This is how I implemented it eventually. Works well for me:
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 5)
desired_url = "https://yourpageaddress"
def wait_for_correct_current_url(desired_url):
wait.until(
lambda driver: driver.current_url == desired_url)
I was thinking to do that somehow with WebDriverWait
Exactly. First of all, see if the built-in Expected Conditions may solve that:
title_is
title_contains
Sample usage:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
wait.until(EC.title_is("title"))
wait.until(EC.title_contains("part of title"))
If not, you can always create a custom Expected Condition to wait for url to match a desired regular expression.
To really know that the URL has changed, you need to know the old one. Using WebDriverWait the implementation in Java would be something like:
wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.not(ExpectedConditions.urlToBe(oldUrl)));
I know the question is for Python, but it's probably easy to translate.
Here is an example using WebdriverWait with expected_conditions:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
url = 'https://example.com/before'
changed_url = 'https://example.com/after'
driver = webdriver.Chrome()
driver.get(url)
# wait up to 10 secs for the url to change or else `TimeOutException` is raised.
WebDriverWait(driver, 10).until(EC.url_changes(changed_url))
Use url_matches Link to match a regex pattern with a url. It does re.search(pattern, url)
from selenium import webdriver
import re
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
pattern='https://www.example.com/'
driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)
wait.until(EC.url_matches(pattern))

Categories

Resources