¿Cómo puedo seleccionar un elemento html sin importar en qué marco se encuentre en Selenium?

Resuelto Alex asked hace 6 años • 2 respuestas

Estoy intentando seleccionar un elemento que reside dentro de un iframe y probablemente en otros iframes.

¿Es de alguna manera posible seleccionar un elemento dentro de algún (sub)iframe en (python)selenium sin seleccionar los iframes antes? ¿Hay alguna manera de 'recorrer cada iframe' de alguna manera y comprobar dónde encontrar mi elemento...?

¿Y cómo hacer eso en el caso de que los elementos, el material html y los iframes estén a punto de cargarse...?

Alex avatar Dec 12 '17 17:12 Alex
Aceptado

No , no es posible interactuar con ningún WebElement dentro de <iframe>Selenium sin cambiar al respectivo iframe.

Razón :

Cuando se carga una página, el foco de Selenium permanece de forma predeterminada en la ventana superior . La ventana superior contiene la otra <iframes>y los conjuntos de marcos . Entonces, cuando necesitamos interactuar con un WebElement que está dentro de un iframe, tenemos que cambiar al respectivo <iframe>mediante uno de los métodos que se mencionan a continuación:


Métodos de cambio de marco:

Podemos cambiar a fotogramas de 3 formas.

Por nombre de cuadro :

Atributo de nombre del iframe a través del cual podemos cambiar a él.

Ejemplo:

driver.switch_to.frame("iframe_name")

Por ID de cuadro :

Atributo ID del iframe a través del cual podemos cambiar a él.

Ejemplo:

driver.switch_to.frame("iframe_id")

Por índice de fotogramas :

Supongamos que si hay 10 marcos en la página, podemos cambiar al iframe usando el índice.

Ejemplo:

driver.switch_to.frame(0)
driver.switch_to.frame(1)

Volviendo al marco principal :

Podemos volver al marco principal usando default_content()oparent_frame()

Ejemplo:

driver.switch_to.default_content()
driver.switch_to.parent_frame()

Un mejor enfoque para cambiar de marco:

Una mejor manera de cambiar de marco será inducir WebDriverWaitla disponibilidad del marco deseado con la siguiente expected_conditionsconfiguración :frame_to_be_available_and_switch_to_it

  • A través de ID de marco :

     WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.ID,"id_of_iframe"))
    
  • A través del nombre del marco :

     WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.NAME,"name_of_iframe")))
    
  • A través del marco XPath :

     WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"xpath_of_iframe")))
    
  • A través del marco CSS :

     WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"css_of_iframe")))
    

Referencia

Puede encontrar una discusión detallada relevante en:

  • Formas de manejar #documento en iframe
undetected Selenium avatar Dec 12 '2017 11:12 undetected Selenium

Escribir su propio buscador recursivo debería ser bastante fácil. Disculpas, no conozco Python pero en Java sería algo como:

public void findInAllFrames(WebElement e, String targetIdStr) {

    List<WebElement> l = e.findElements(By.tagName("iframe"));

    for(int inx=0; inx<l.size(); inx++) {
        List<WebElement> targets = l.get(inx).findElements(By.id(targetIdStr));
        if(targets.size()>0) {
            // Do something with your targets
        }

        findInAllFrames(l.get(inx), targetIdStr);
    }
}
MonkeyTester avatar Dec 12 '2017 11:12 MonkeyTester