Search code examples
pythonseleniumautomation

selenium webdriver can not find interactive web elements


i am trying to automatically fill this form to download some documents from this mexican government webpage for my family (they have to download them at least monthly) using selenium webdriver in python but it yields this error in all form elements:

NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":
  (Session info: chrome=104.0.5112.81)
Stacktrace:
Backtrace:
    Ordinal0 [0x00F85FD3+2187219]
    Ordinal0 [0x00F1E6D1+1763025]
    Ordinal0 [0x00E33E78+802424]
    Ordinal0 [0x00E61C10+990224]
    Ordinal0 [0x00E61EAB+990891]
    Ordinal0 [0x00E8EC92+1174674]
    Ordinal0 [0x00E7CBD4+1100756]
    Ordinal0 [0x00E8CFC2+1167298]
    Ordinal0 [0x00E7C9A6+1100198]
    Ordinal0 [0x00E56F80+946048]
    Ordinal0 [0x00E57E76+949878]
    GetHandleVerifier [0x012290C2+2721218]
    GetHandleVerifier [0x0121AAF0+2662384]
    GetHandleVerifier [0x0101137A+526458]
    GetHandleVerifier [0x01010416+522518]
    Ordinal0 [0x00F24EAB+1789611]
    Ordinal0 [0x00F297A8+1808296]
    Ordinal0 [0x00F29895+1808533]
    Ordinal0 [0x00F326C1+1844929]
    BaseThreadInitThunk [0x75806739+25]
    RtlGetFullPathName_UEx [0x772F8FEF+1215]
    RtlGetFullPathName_UEx [0x772F8FBD+1165]

i tried using ID, XPATH, full XPATH and CSS selector but none of them work. I also tried to check each element by themselves in a separate script and the result is the same. this is my code:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import re
import datetime
import time
today=today=datetime.date.today()
driver=webdriver.Chrome(executable_path=r"C:\Users\HP\Downloads\chromedriver_win32\chromedriver.exe")
driver.implicitly_wait(30)
for i in range(3):
    try:
        driver.get("http://rh.imss.gob.mx/tarjetonjubilados/(S(zh0qyvr1lwrxezeum4tjlypg))/default.aspx")
        break
    except:
        pass
#delchoice=driver.find_element(By.ID,"ddlDelegacion")
#delchoice.click()
delegacion=driver.find_element(By.XPATH,"/html/body/table/tbody/tr[2]/td/table/tbody/tr[2]/td[3]/select/option[37]")
delegacion.elect_by_index(integer redacted)
user=driver.find_element(By.ID,"txtUsuario")
user.send_keys(string redacted)
password=driver.find_element(By.ID,"txtContraseña")
password.send_keys(string redacted)
nextpage=driver.find_element(By.ID,"btnIngresar")
time.sleep(30)
for i in range(3):
    try:
        filebutton=driver.find_element(By.ID,"rdoArchivo")
        filebutton.click()
        break
    except:
        driver.navigate().refresh()
        time.sleep(30)
tarjetonbutton=driver.find_element(By.ID,"rdoTarjeton")
tarjetonbutton.click()
tarjetonchoicebutton=driver.find_element(By.XPATH,"/html/body/table/tbody/tr[6]/td/div/div[3]/div[3]/div/table/tbody/tr[2]/td[3]")
tarjetonchoicebutton.click()
tarjetondate=tarjetonchoicebutton.text
tarjetonredate=re.search(r"(?<=\d{2}\/)\d{2}(?=\/\d{4}\s\-)",tarjetondate)
tarjetonmonth=tarjetonredate.group
print(tarjetonmonth)
thismonth=str(today.month)
print(tarjetonmonth)
if thismonth==tarjetonmonth:
    downloadbutton=driver.find_element(By.ID,"btnAceptar")
    downloadbutton.click
driver.quit()

Another curious issue is that it do work with other page elements, just not the form ones


Solution

  • The issue here is that all the form is inside an iframe which means you need to actually switch to it before searching for the elements (actually the same will be needed for the next page). This approach by @undetected Selenium works pretty well:

    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='ifrPaginaSecundaria']")))
    Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//select[@id='ddlDelegacion']")))).select_by_index(INTEGER EXPUNGED)
    

    although it requires 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
    from selenium.webdriver.support.ui import Select
    

    with all of that the full code ends up like this:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support.ui import Select
    from selenium.webdriver.support import expected_conditions as EC
    import re
    import datetime
    import time
    today=today=datetime.date.today()
    driver=webdriver.Chrome(executable_path=r"C:\Users\HP\Downloads\chromedriver_win32\chromedriver.exe")
    driver.implicitly_wait(10)
    for i in range(3):
        try:
            driver.get("http://rh.imss.gob.mx/tarjetonjubilados/(S(zh0qyvr1lwrxezeum4tjlypg))/default.aspx")
            break
        except:
            driver.navigate().refresh()
    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='ifrPaginaSecundaria']")))
    Select(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//select[@id='ddlDelegacion']")))).select_by_index(INTEGER EXPUNGED)
    user=driver.find_element(By.ID,"txtUsuario")
    user.send_keys(STRING EXPUNGED)
    password=driver.find_element(By.ID,"txtContraseña")
    password.send_keys(STRING EXPUNGED)
    nextpage=driver.find_element(By.ID,"btnIngresar")
    nextpage.click()
    time.sleep(10)
    for i in range(3):
        try:
            driver.switch_to.default_content()
            WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='ifrPaginaSecundaria']")))
            filebutton=driver.find_element(By.ID,"rdoArchivo")
            filebutton.click()
            break
        except:
            driver.navigate().refresh()
            time.sleep(5)
    tarjetonbutton=driver.find_element(By.ID,"rdoTarjeton")
    tarjetonbutton.click()
    tarjetonchoicebutton=driver.find_element(By.XPATH,"/html/body/table/tbody/tr[6]/td/div/div[3]/div[3]/div/table/tbody/tr[2]/td[3]")
    tarjetonchoicebutton.click()
    tarjetondate=tarjetonchoicebutton.text
    tarjetonredate=re.search(r"(?<=\d{2}\/)\d{2}(?=\/\d{4}\s\-)",tarjetondate)
    tarjetonmonth=int(tarjetonredate.group())
    thismonth=int(today.month)
    if thismonth==tarjetonmonth:
        print("download cleared")
        downloadbutton=driver.find_element(By.ID,"btnAceptar")
        downloadbutton.click()