Mercedes Terragno
Mercedes Terragno

Reputation: 11

Python Selenium Webdriver Message: Unable to locate element:

I'm trying to write a Python script using selenium's webdriver, to automate the task of uploading invoices to the federal online ledger.

I know this is a common question, but after reading many questions in SO and trying their answers, I couldn't find a solution.

This is the html code I want to select and click on:

<input id="idcontribuyente" type="hidden" name="idContribuyente">
<input class="btn_empresa ui-button ui-widget ui-state-default ui-corner-all" type="button" style= "width:100%" onclick="document.getElementById('idcontribuyente').value='0';document.seleccionaEmpresaForm.submit();" role="button"> 

These are the main things I've tried so far:

(first with the WebDriverWait() and then with time.sleep(20), just in case there was an error there)

#1
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, "btn_empresa")))
empresa_btn = driver.find_element_by_class_name('btn_empresa')
empresa_btn.click()

#2
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all')))
empresa_btn = driver.find_element_by_css_selector('.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all')
empresa_btn.click()

#3
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, "//input[@type='button']")))
empresa_btn =  driver.find_element_by_css_selector("//input[@type='button']")
empresa_btn.click()

#4
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, "//input[@type='button']")))
empresa_btn = driver.find_element_by_xpath("//input[@type='button']")
empresa_btn.click()

#5
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//td[@align="center"]/input')))
empresa_btn =  driver.find_element_by_css_selector('//td[@align="center"]/input')
empresa_btn.click()

#6
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH,"//input[@class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']")))
empresa_btn = driver.find_element_by_xpath("//input[@class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']")
empresa_btn.click()

The error when using time.sleep(20):

selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: element_name

The error when using WebDriverWait():

selenium.common.exceptions.TimeoutException: Message:

Here's the full html code: enter image description here

I'm pretty new to this. What am I doing wrong?

many thanks in advance!

UPDATE - SOLUTION:

I found a way, I've used a Selenium IDE and exported the code to inspect it. Apparently it had to do with switching windows. This code works (although it may be more verbose than it needs to be):

vars = {}
vars["window_handles"] = driver.window_handles

# This line already worked before. It is for the previous page
driver.find_element_by_xpath("//div[@title='rcel']").click()

# Here it comes the way to select and click on the problematic button
def wait_for_window(timeout = 2):
    time.sleep(round(timeout / 1000))
    wh_now = driver.window_handles
    wh_then = vars["window_handles"]
    if len(wh_now) > len(wh_then):
        return set(wh_now).difference(set(wh_then)).pop()

vars["win806"] = wait_for_window(2000)
driver.switch_to.window(vars["win806"])
driver.find_element(By.CSS_SELECTOR, ".btn_empresa").click()

This is how the actual webpage looked like: red triangle indicates the button I wanted to click on

Upvotes: 1

Views: 225

Answers (3)

Diego
Diego

Reputation: 1

#emitir factura  
emitirf_input =driver.find_element(By.ID, "bBtn1")   
emitirf_input.send_keys(Keys.RETURN)
time.sleep(3)
driver.switch_to.window(driver.window_handles[1])
#cargo la pestaña nueva que se abre
driver.get("https://fe.afip.gob.ar/rcel/jsp/index_bis.jsp#")
#contribuyente
contri_input =driver.find_element(By.ID, "idcontribuyente")
contri_input =driver.find_element(By.CLASS_NAME, 'btn_empresa')
contri_input.send_keys(Keys.RETURN)
time.sleep(3)

Upvotes: -1

vitaliis
vitaliis

Reputation: 4212

First wait, then click:

WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all')))
empresa_btn = driver.find_element_by_css_selector('.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all').click()

Some of the steps you've tried were very close.

If the element you want to click is hidden, try using driver.execute_script:

element = driver.find_element_by_css_selector("#idcontribuyente")
driver.execute_script("$(arguments[0]).click();", element)

Update 1, try to click the second input:

element = driver.find_element_by_css_selector(".btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all")
driver.execute_script("$(arguments[0]).click();", element)

Update 2, probably you have few similar css locators similar to above: try using:

tr:nth-of-type(4)>td>.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all

Update 3 Check if your button is located inside shadow DOM. If it is - none of the methods you tried will work. Check how to enable showing shadow DOM.

Update 4 As mentioned in the comment to your question, your second xpath was good. Try using it this way:

WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']")))
empresa_btn = driver.find_element_by_xpath("//input[@class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']").click()

Upvotes: 1

JD2775
JD2775

Reputation: 3801

Maybe try...

driver.find_element_by_xpath("//input[@id='idcontribuyente']/following-sibling::input")

Since it is 2 input tags next to each other, this finds the one by ID first and takes the input sibling directly after it. Not sure it will work since I can't access the URL, but give it a shot

Upvotes: 1

Related Questions