I am trying to click on a button if an element is found on the page. The element is on the page most of the time. 3 times work, and 1 time doesn't work.
Here is my code:
elements = driver.find_elements_by_xpath("//h2[contains(text(),'No results found')]")
if (len(elements)>0):
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CLASS_NAME, 'ut-navigation-button-control'))).click()
else:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(., 'Buy Now')]"))).click()
And below is the error I get sometime:
ElementClickInterceptedException: Message: Element <button class="ut-navigation-button-control"> is not clickable at point (128,80) because another element <div class="ut-click-shield showing interaction"> obscures it
try:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(., 'Buy Now')]"))).click()
except:
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CLASS_NAME, 'ut-navigation-button-control'))).click()
It's working like this, but it take a lot of time during the except. Does anyone know how to make it to go quickly through except?
The element with text as No results found would appear only after a unsuccessful search. On a successful search, to click on the desired element, you have to induce WebDriverWait for the element_to_be_clickable() and you can use the following xpath based Locator Strategies:
try:
# wait for the visibility of the element with text as "No results found"
WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//h2[text()='No results found']")))
# if the element with text as No results found, induce WebDriverWait for invisibilityOfElement obscuring the clickable element
new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("//div[#class='ut-click-shield showing interaction']")));
# once the invisibilityOfElement obscuring the clickable element is achieved, click on the desired element inducing WebDriverWait
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='ut-navigation-button-control']"))).click()
except TimeoutException:
# if search for the element with text as "No results found" raises "TimeoutException" exception click on the element with text as "Buy Now" inducing WebDriverWait
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(,. 'Buy Now')]"))).click()
You can perform JavaScriptExecutor click on the element as it directly performs the action on the div and is not affected by the position of the element on the page.
You can do it like:
button = driver.find_element_by_xpath("//button[contains(text(),'Back')]")
driver.execute_script("arguments[0].click();", button)
Related
I am testing a webapp created with python dash using selenium. I am trying to click a tab but always get the ElementClickIntercepted Exception.
Note: Of course I stumbled over similiar problems but most times the problem is that the element cannot be clicked as is did not load yet - I already built in waits! - or the fact that another element would receive the click which cannot be the case either. Note that the first item is always preselected and i want to choose the second.
#Selct X-Axis
x_axis = driver.find_element(By.XPATH, "//*[#id='navbar']/a[2]")
x_axis.click()
driver.implicitly_wait(2)
try:
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//a[text()='Even']"))
)
except:
raise Exception
even= driver.find_element(By.XPATH, "//a[text()='Even']")
even.click()
Exception snapshot:
HTML snapshot:
Based on what you've posted, By.XPATH, "//a[text()='Even']" is probably selecting an HTML element different from what you're expecting.
There appears to be an <a> with text that starts with 'Even', but you've shown nothing with text that equals 'Even'.
BTW, when asking a question, you ought to at least paste the relevant HTML as text, rather than as a screenshot.
Use contains(text(), 'even') instead of text()='even' in your XPath. Because, text()='even' means the text must be 'even' but not contain 'even', and in your HTML code, the text seems not only have 'even'.
To click on either of the element instead of presence_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
$$$ Response:
Using PARTIAL_LINK_TEXT:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Response"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[starts-with(#id, 'content')]//ul//div[#class='nav-item']//a[contains(., 'Response')]"))).click()
Even $$$:
Using PARTIAL_LINK_TEXT:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Even"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[starts-with(#id, 'content')]//ul//div[#class='nav-item']//a[starts-with(., 'Even')]"))).click()
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
My selenium python script can't click the button with either click() or `driver.execute_script("arguments[0].click();", continue_). It worked for previous buttons but this particular button is only detected but can't be clicked.
Here is the code:
WebDriverWait(driver, 60).until(EC.presence_of_element_located(
(By.XPATH, "//button[contains(text(),'Continue')]")))
continue_ = driver.find_element(
By.XPATH, "//button[contains(text(),'Continue')]")
driver.execute_script("arguments[0].click();", continue_)
Update:
The answers didn't work for me. I tried adding prints to see where it stops.
WebDriverWait(driver, 60).until(EC.presence_of_element_located(
(By.XPATH, "//button[contains(text(),'Continue')]")))
print("Presence Located")
continue_ = driver.find_element(
By.XPATH, "//button[contains(text(),'Continue')]")
print("Continue Button Found")
driver.execute_script("arguments[0].click();", continue_)
print("Continue Button Clicked")
My console displays all prints till the "Continue Button Clicked" but is still not clicking the Continue so my bot can't progress through it's script. I don't know if it's any help but can't think of anything else.
Update
Tried using is_displayed() on the continue button it returned True.
The <button> element have the innerText spanned over multiple lines.
Solution
To click on the element instead of presence_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using XPATH and starts-with():
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#type='submit' and starts-with(., 'Continue')]"))).click()
Using XPATH and contains():
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#type='submit' and contains(., 'Continue')]"))).click()
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
I am currently learning the use of selenium with python, and tried to collect some data. I have been struggling for the last couple days with clicking on a dropdown not accessible by Select method.
I looked at A LOT of questions on SOF, blogs, tutorials ... and could not find the answer to my problem.
The dropdown is accessible to this website <"https://en.volleyballworld.com/volleyball/competitions/olympics-2020/schedule/11349/">, then by clicking on the "Box Score" tab. Just below the teams flags, you'll see the dropdown with "ALL SETS" writing in it.
I would like to access the data from "SET 1", "SET 2", "SET 3". My guess would be to click on the dropdown, then click on "SET 1" and so on. But I couldn't make the code work to click on the dropdown.
Below is my code :
PATH = "C:\Program Files\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://en.volleyballworld.com/volleyball/competitions/olympics-2020/schedule/11349/")
#implicit wait to be sure the elements we want are loaded when we try accessing them
driver.implicitly_wait(5)
actions = ActionChains(driver)
#clicking on button
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "tab-title_boxscore")))
element.click() #mimic clicking on the clickable element
dropdown = WebDriverWait(driver, 10).until(EC.element_to_be_clickable(
(By.LINK_TEXT, "ALL SETS"))).click()
first_set = WebDriverWait(driver, 10).until(EC.element_to_be_clickable(
(By.LINK_TEXT, "SET 1"))).click()
Many thanks for your time and answer !
To click() on the element with text as ALL SETS and then to click on the element with text as SET 1 instead of presence_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following Locator Strategies:
Code Block:
driver.get("https://en.volleyballworld.com/volleyball/competitions/olympics-2020/schedule/11349/")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button#onetrust-accept-btn-handler"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.tab-title_boxscore"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.tab-title_all"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='All Sets']//following::li[1]/a/span"))).click()
Browser Snapshot:
I am trying to write a code that is able to auto apply on job openings on indeed.com. I have managed to reach the last stage, however, the final click on the application form is giving me a lot of trouble. Please refer the page as below
Once logged in to my profile, I go to the relevant search page, click on the listing I am interested in and then on the final page (shown above) I am trying to click on the continue button using xpath. For the previous step (also a page on the same form), the form had multiple iframes which I was able to switch successfully. Now for the current page, I am stuck as the click function does not do anything. I have written the following code:
driver.get("https://in.indeed.com/jobs?q=data%20analyst&l=Delhi&vjk=5c0bd416675cf4e5")
driver.find_element_by_xpath('//*[#id="apply-button-container"]/div[1]/span[1]').click()
time.sleep(5)
frame_1 = driver.find_element_by_css_selector('iframe[title="Job application form container"')
driver.switch_to.frame(frame_1)
frame_2 = driver.find_element_by_css_selector('iframe[title="Job application form"]')
driver.switch_to.frame(frame_2)
continue_btn = driver.find_element_by_css_selector('#form-action-continue')
continue_btn.click()
driver.find_element_by_xpath('//*[#id="form-action-continue"]').click()
I have tried switching the iframes again for this step but nothing happens. Even the .click() function does not do anything.
Will appreciate some help on this.
The element Continue is within nested <iframe> elements so you have to:
Induce WebDriverWait for the parent frame to be available and switch to it.
Induce WebDriverWait for the child frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
driver.get("https://in.indeed.com/jobs?q=data%20analyst&l=Delhi&vjk=5c0bd416675cf4e5")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.indeed-apply-button-label"))).click()
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[id^='indeedapply-modal-preload']")))
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='Job application form']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button#form-action-continue"))).click()
Using XPATH:
driver.get("https://in.indeed.com/jobs?q=data%20analyst&l=Delhi&vjk=5c0bd416675cf4e5")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[#class='indeed-apply-button-label']"))).click()
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[starts-with(#id, 'indeedapply-modal-preload')]")))
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#title='Job application form']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#id='form-action-continue']"))).click()
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
Browser Snapshot:
Reference
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Switch to an iframe through Selenium and python
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element while trying to click Next button with selenium
selenium in python : NoSuchElementException: Message: no such element: Unable to locate element
The site is https://www.webstaurantstore.com/25887/commercial-gas-ranges.html?page=1 . When I want to localize the search field in the top right corner and send then keys there, it works. But when I want to do the same operation after executing one search it does not work. selenium can locate element, but can not send keys to it. Why something like this happening and how can I avoid that?
while True:
try:
a = self.webdriver.find_element_by_xpath('/html/body/div[3]/div[1]/div[2]/div[2]/div/div[2]/div/form/div/input')
except:
pass
else:
a.send_keys(i.text[1:])
break
Error:
>>>selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
(Session info: chrome=81.0.4044.138)
I believe the problem is the element that you've referred was deleted from the DOM.
That's why you get the exception, the element itself no longer exist even it's showed on UI.
You may use try/catch with the same block of instructions.
try:
line1
line1
...
except:
line1
line1
...
The is a simple idea to solve the problem like yours, but not the best solution, I will update my answer if I have better than it.
poll_frequency-to sleep in between calls
and refresh your page if you catch an exception.
try:
wait = WebDriverWait(driver, 5, poll_frequency=1)
a = self.webdriver.find_element_by_xpath('/html/body/div[3]/div[1]/div[2]/div[2]/div/div[2]/div/form/div/input')
element = wait.until(expected_conditions.visibility_of_element_located(a))
except:
driver.refresh()
To send a character sequence to the Search box second time after the first search using Selenium you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
CSS_SELECTOR:
driver.get("https://www.webstaurantstore.com/25887/commercial-gas-ranges.html?page=1")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='searchval']"))).send_keys("Oven")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[value='Search']"))).click()
search = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='searchval']")))
search.click()
search.clear()
search.send_keys("Bowls")
XPATH:
driver.get("https://www.webstaurantstore.com/25887/commercial-gas-ranges.html?page=1")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='searchval']"))).send_keys("Oven")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#value='Search']"))).click()
search = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='searchval']")))
search.click()
search.clear()
search.send_keys("Bowls")
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