Reputation: 579
I am trying to click on a button but getting this error message: The element I am trying to click does exist on the page but I am not sure why it's saying that the element does not exist:
Message: no such element: Unable to locate element: {"method":"xpath","selector":"//button[@class="vote_button mfp-voteText"]"}
Below is my code:
driver.get('https://trupanion.com/canada/members/contest?pixlee_album_photo_id=427049511')
time.sleep(10)
try:
vote = driver.find_element_by_xpath('//button[@class="vote_button mfp-voteText"]')
vote.click()
except Exception as e:
print(e)
Below is the XPath in chrome dev tool which shows it's correct:
Upvotes: 2
Views: 7193
Reputation: 7563
It inside a <frame>
tag, switch it first:
driver.get('https://trupanion.com/canada/members/contest?pixlee_album_photo_id=427049511')
time.sleep(10)
try:
#switch it first
driver.switch_to.frame(driver.find_element_by_id('pixlee_lightbox_iframe'))
vote = driver.find_element_by_xpath('//button[@class="vote_button mfp-voteText"]')
vote.click()
except Exception as e:
print(e)
But note time.sleep(..)
is a bad idea.
You can learn selenium waits here:
selenium-python.readthedocs.io/waits.html
And for switch a frame:
.frame_to_be_available_and_switch_to_it
Although your xpath will work, the css selector looks better:
vote = driver.find_element_by_css_selector('button.vote_button.mfp-voteText')
Upvotes: 1
Reputation: 193088
The desired element is within an <iframe>
so you have to:
Induce WebDriverWait for the desired 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://trupanion.com/members/contest?pixlee_album_photo_id=427049511')
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#pixlee_lightbox_iframe")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.vote_button.mfp-voteText"))).send_keys("test")
Using XPATH
:
driver.get("https://trupanion.com/members/contest?pixlee_album_photo_id=427049511")
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='pixlee_lightbox_iframe']")))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@class='vote_button mfp-voteText']"))).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:
You can find a couple of relevant discussions in:
Upvotes: 4
Reputation: 2685
Try to use css selector
instead of XPATH
with the WebdriverWait()
function. It will wait X seconds for an element to be clickable and will click it as soon as it is present. However, you need to switch to the frame that you have to find by a frame
selector.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
self.webdriver.switch_to_frame(self.webdriver.find_element_by_css_selector('frame'))
try:
WebDriverWait(webdriver,time).until(EC.element_to_be_clickable((By.CSS_SELECTOR,path)))
except Exception as e:
print(e)
Upvotes: 1