Selenium Python: Element is not clickable - python

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

Related

XPATH cannot locate element with colon in its ID or name

I am on a side project to write python script to auto-login a website.
I am trying to use python script to launch FireFox browser and auto-login into a website
Below is the source code of the element i'm trying to locate:
source code
I used below
item_email= WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH, "//input[contains(#id,'username')]")))
or below
item_email= WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH, "//input[contains(#id,'username')]")))
or below
item_email = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH, "//input[#id='j_id0:j_id5:loginComponent:loginForm:username']")))
They all ended up with selenium.common.exceptions.TimeoutException
I was able to locate elements when the input ID didn't have colons (not with namespace, i guess)
erhai950,
Explicit wait will always end up in selenium.common.exceptions.TimeoutException exception if the element is not found in HTMLDOM for any reason.
You can try the below xpath:
//input[contains(#id,'username') and #placeholder='Email']
Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste and see //input[contains(#id,'username') and #placeholder='Email'] if your desired element is getting highlighted or not.
Now if we have 1/1 matching entry then try below code:
item_email = driver.find_element(By.XPATH, "//input[contains(#id,'username') and #placeholder='Email']")
or
item_email= WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH, "//input[contains(#id,'username') and #placeholder='Email']")))
Also check if this web element is in iframe or not.
Given the HTML:
the element is a <input> element which would accept text input.
Solution
Ideally to send a character sequence to an <input> element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.form-group input[id$='username'][name$='username'][placeholder='Email']"))).send_keys("erhai950")
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='form-group']//input[contains(#id, 'username') and contains(#name, 'username')][#placeholder='Email']"))).send_keys("erhai950")
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

How to click on td element using selenium python

So I'm Fairley new to selenium and I'm attempting click on a table but I can't seem to find it.
Below I have posted my code along with a screen shot of what I'm trying to click on.
Here is my code:
competitorPrices = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.LINK_TEXT, "Competitor Prices"))).click()
HTML snapshot:
Error:
Element snapshot:
I would try something like this:
...
import time
time.sleep(5)
xpath = "//*[contains(text(),'Competitor Prices')]"
element = driver.find_element(by=By.XPATH, value=xpath)
competitorPrices = driver.execute_script("$(arguments[0]).click();", element)
Sometimes the method element_to_be_clickable doesn't work out of the box. In this cases to debug I use time.sleep so I can understand better the problem
The desired element is a <td> not an <a> tag. Hence LINK_TEXT won't work.
Moreover click() doesn't returns anything, so competitorPrices will be always None which you may remove.
Solution
You can use either of the following locator strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "table#tblTabStrip td[ch^='CompetitorPrices']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//table[#id='tblTabStrip']//td[text()='Competitor Prices']"))).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

Python Selenium get "sold items" information from eBay Productpage

I want to click on the following element "23 verkauft" on an eBay productpage you can see it on this screenshot:
Here is the HTMl Code of this Element:
Here is my Code but the webdriver cant locate the element or can't click on it.
sold = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//span[#class, 'vi-txt-underline']")))
sold.click()
You were close enough. But you have to make to adjustments:
Instead of (By.XPATH, "//span[#class, 'vi-txt-underline']") you need to use (By.XPATH, "//span[#class='vi-txt-underline']")
Instead of presence_of_element_located() you need to use element_to_be_clickable()
Solution
To click on the element with text as 23 verkauft you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using LINK_TEXT:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "23 verkauft"))).click()
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.vi-txt-underline"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[text()='23 verkauft']"))).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
You have an error with your locator.
Instead of
//span[#class, 'vi-txt-underline']
It should be
//a[#class='vi-txt-underline']
Also instead of presence_of_element_located you should use visibility_of_element_located since the former method will wait for more mature element state, not only presented on the page but also visible.
Also you can click on the element there directly, no need for the additional code line.
So your code could be
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//a[#class='vi-txt-underline']"))).click()

Selenium find attribute value (Python)

I would like to get all attribute values names 'href' from a website, there are like 10 of them. I have successfully got one using the following method:
url = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[1]/div/div[1]/span/a"))).get_attribute("href")
The problem with this is it's only giving back one not all of them. I have tried to go by ID but it doesn't return anything:
url = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "a"))).get_attribute("href")
Also, the other href values are located in different xpaths:
/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[2]/div/div[1]/span/a
/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[3]/div/div[1]/span/a
/html/body/div[2]/div[2]/div/div/div[2]/section[1]/div/div[2]/div[3]/ul/li[4]/div/div[1]/span/a
Here's my element:
<a ph-tevent="job_click" ref="linkEle" href.bind="getUrl(linkEle, 'job', eachJob, '', eachJob.jobUrl)" data-ph-at-id="job-link" data-ph-id="ph-page-element-page20-CRUCUZ" class="au-target" au-target-id="181" ph-click-ctx="job" ph-tref="12313123213" ph-tag="ph-search-results-v2" href="https://hyperlink.com" data-ph-at-job-title-text="title" data-ph-at-job-location-text="Unknown" data-ph-at-job-location-area-text="asd" data-ph-at-job-category-text="Manufacturing" data-access-list-item="2" data-ph-at-job-id-text="A123124" data-ph-at-job-type-text="Regular" data-ph-at-job-industry-text="Manufacturing" data-ph-at-job-post-date-text="2021-12-09T00:00:00.000Z" data-ph-at-job-seqno-text="ASD212ASFS" aria-label="Senior Manager">
<div class="job-title" data-ph-id="ph-page-element-page20-0Mi3Ce">
<!--anchor-->
<!--anchor-->
<span data-ph-id="ph-page-element-page20-PLxqta">Senior Manager </span>
</div><!--anchor--> </a>
Any help is appreciated!
For finding more than one web element, you should either use find_elements or if you are using Explicit waits then you can use presence_of_all_elements_located or visibility_of_all_elements_located.
Based on the HTML that you've shared, if
this css
a[ph-tevent='job_click'][ref='linkEle']
or this xpath
//a[#ph-tevent='job_click' and #ref='linkEle']
represent all the nodes, to check below are the steps:
Please check in the dev tools (Google chrome) if we have all desired nodes entry in HTML DOM or not.
Steps to check:
Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste the xpath and see, if your desired elements are getting highlighted or not.
If they are then the below code should work:
for ele in driver.find_elements(By.XPATH, "//a[#ph-tevent='job_click' and #ref='linkEle']"):
print(ele.get_attribute('href'))
To extract the value of the href attributes using Selenium and python you have to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "a[ph-tevent='job_click'][ref='linkEle'][data-ph-at-id='job-link'][ph-click-ctx='job'][href]")))])
Using XPATH:
print([my_elem.get_attribute("href") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//a[#ph-tevent='job_click' and #ref='linkEle'][#data-ph-at-id='job-link' and #ph-click-ctx='job'][#href]")))])
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

How to send_keys within the Search field element second time that exists

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

Categories

Resources