I can’t get element on PHP website with Selenium



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

enter image description here

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() 

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()


Source: stackoverflow