I need to build a script to automate action on this website that is builded using PHP.
For that, I’m using the Selenium package for python.
So I instantiate the browser and made login using the xpath to get the elements
browser = webdriver.Chrome() browser.get('https://openboxmobile.redicom.cloud/login.php') username = browser.find_element_by_xpath('//*[@id="_utilizador"]') password = browser.find_element_by_xpath('//*[@id="_password"]') username.send_keys(USERNAME) password.send_keys(PASSWORD, Keys.ENTER)
The problem
After log-in on the page, I need to click on a input type=”button”, so I’m trying to get the element using xpath again.
product_import = browser.find_element_by_xpath('//*[@id="but_2"]')
but the following exception was raised.
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="but_2"]"} (Session info: chrome=94.0.4606.71)
What I already tryed
I tryed to get the element using full x-path and id
I also printed the base64 image after loging to check if the page was updating and it is.
IMAGE OF PAGE HTML
Update
I looked at some other questions and I found this, so I tried to run the following code, but a TimeoutException was raised.
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//*[@id="imain"]'))) WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="but_2"]'))).click()
Update 2
iframe = driver.find_element_by_xpath('/html/body/iframe') driver.switch_to.frame(iframe) product_import = driver.find_element_by_xpath('//*[@id="but_2"]')
this code crashed on the product_import
line, so, apparently, the driver switched to the correct iframe, but selenium.common.exceptions.NoSuchElementException:
was raised
SOLUTION
I used chromium to get full xpath of two frames that was wrapping my application (I discovered that by getting the full xpath of my button and I see that was too short, that because he was wrapped).
So I ran the following code
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "/html/body/iframe"))) WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "/html/frameset/frameset/frameset[2]/frame[1]"))) import_input = driver.find_element_by_xpath("/html/body/div[3]/div[3]/table/tbody/tr/td[1]/input[2]") import_input.send_keys(Keys.ENTER)
If the button was actually a button and not an input type button he could be click by using this command.
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[3]/div[3]/table/tbody/tr/td[1]/input[2]"))).click()
Advertisement
Answer
The input tag is in iframe, in Selenium you will have to switch to iframe first and then you can interact with the input tag.
Please switch it like this :
WebDriverWait(browser, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "mainframe"))) product_import = browser.find_element_by_xpath('//*[@id="but_2"]')
You will have to import these :
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC
You will also have to make sure that the input is under just this iframe. There could be a possibility of nested iframes
as well.
Also, iframe id has to be unique in HTMLDOM
to make this to work.
PS : Please check in the dev tools
(Google chrome) if we have unique 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 element
is getting highlighted with 1/1
matching node.
Also, I would say if id is unique please use id not xpath for this :
browser.find_element_by_xpath('//*[@id="but_2"]')
A way better approach would be with WebDriverWait
element_to_be_clickable
. Something like this :
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.ID, "but_2"))).click()