Selenio “selenium.common.exceptions.NoSuchElementException” cuando se usa Chrome

Estoy tratando de jugar QWOP usando Selenium en Chrome pero sigo recibiendo el siguiente error:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element {"method":"id","selector":"window1" (Session info: chrome=63.0.3239.108 (Driver info: chromedriver=2.34.522913 (36222509aa6e819815938cbf2709b4849735537c), platform=Linux 4.10.0-42-generic x86_64) 

mientras se usa el siguiente código:

 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains import time browser = webdriver.Chrome() browser.set_window_size(640, 480) browser.get('http://www.foddy.net/Athletics.html?webgl=true') browser.implicitly_wait(10) canvas = browser.find_element_by_id("window1") canvas.click() while (True): action = ActionChains(browser) action.move_to_element(canvas).perform() canvas.click() canvas.send_keys("q") 

El mismo código funciona perfectamente en Firefox, pero como quiero usar la capacidad de Chrome para ejecutar un juego webgl en modo sin cabeza, realmente no puedo cambiar a Firefox.

¿Alguna solución para que esto funcione?

NoSuchElementException

selenium.common.exceptions.NoSuchElementException popularmente conocido como NoSuchElementException se define como:

 exception selenium.common.exceptions.NoSuchElementException(msg=None, screen=None, stacktrace=None) 

NoSuchElementException se lanza básicamente en 2 casos de la siguiente manera:

  • Cuando usas :

     webdriver.find_element_by_*("expression") //example : my_element = driver.find_element_by_xpath("xpath_expression") 
  • Cuando usas :

     element.find_element_by_*("expression") //example : my_element = element.find_element_by_*("expression") 

Según los documentos de la API, al igual que cualquier otra selenium.common.exceptions , NoSuchElementException debe contener los siguientes parámetros:

  • msg, pantalla, stacktrace

      raise exception_class(message, screen, stacktrace) selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":".//*[@id='create-portal-popup']/div[4]/div[1]/button[3]"} (Session info: chrome=61.0.3163.100) (Driver info: chromedriver=2.32.498550 (9dec58e66c31bcc53a9ce3c7226f0c1c5810906a),platform=Windows NT 10.0.10240 x86_64) 

Razón

El motivo de NoSuchElementException puede ser uno de los siguientes:

  • La estrategia de localización que ha adoptado no identifica ningún elemento en el DOM de HTML .
  • La estrategia de localización que ha adoptado no puede identificar el elemento ya que no está dentro de la vista del navegador.
  • La estrategia de localización que ha adoptado identifica el elemento pero es invisible debido a la presencia del atributo style = “display: none;” .
  • La estrategia de localización que ha adoptado no identifica de forma única el elemento deseado en el DOM HTML y actualmente encuentra algún otro elemento oculto / invisible .
  • El elemento web que intenta localizar está dentro de una etiqueta .
  • La instancia de WebDriver está buscando el elemento Web incluso antes de que el elemento esté presente / visible dentro del DOM de HTML .

Solución

La solución para abordar la excepción NoSuchElementException puede ser una de las siguientes:

  • Adopte una estrategia de localización que identifique de forma única el elemento web deseado. Puede tomar la ayuda de las Herramientas de desarrollo ( Ctrl + Shift + I o F12 ) y usar el Inspector de elementos .

    Aquí encontrará una discusión detallada sobre cómo inspeccionar el elemento en selenium3.6, ya que Firebug ya no es una opción para el FF 56.

  • Use el método execute_script() para desplazar el elemento hacia adentro y verlo de la siguiente manera:

     elem = driver.find_element_by_xpath("element_xpath") driver.execute_script("arguments[0].scrollIntoView();", elem) 

    Aquí encontrará una discusión detallada sobre Desplazamiento hacia la parte superior de la página en Python usando Selenium

  • El elemento Incase tiene el atributo style = “display: none;” , elimine el atributo mediante el método executeScript() siguiente manera:

     elem = driver.find_element_by_xpath("element_xpath") driver.execute_script("arguments[0].removeAttribute('style')", elem) elem.send_keys("text_to_send") 
  • Para verificar si el elemento está dentro de un recorra el HTML para ubicar la etiqueta respectiva y switchTo() iframe switchTo() deseado al iframe a través de cualquiera de los siguientes métodos:

     driver.switch_to.frame("iframe_name") driver.switch_to.frame("iframe_id") driver.switch_to.frame(1) // 1 represents frame index 

    Aquí puede encontrar una discusión detallada sobre ¿Cómo puedo seleccionar un elemento html sin importar en qué marco se encuentre en selenium? .

  • Si el elemento no está presente / visible en el DOM HTML inmediatamente, induzca a WebDriverWait con el conjunto de las condiciones esperadas al método apropiado de la siguiente manera:

    • Para esperar presencia_de_elemento_locado :

       element = WebDriverWait(driver, 20).until(expected_conditions.presence_of_element_located((By.XPATH, "element_xpath']"))) 
    • Para esperar la visibilidad_de_elemento_locado :

       element = WebDriverWait(driver, 20).until(expected_conditions.visibility_of_element_located((By.CSS_SELECTOR, "element_css") 
    • Para esperar element_to_be_clickable :

       element = WebDriverWait(driver, 20).until(expected_conditions.element_to_be_clickable((By.LINK_TEXT, "element_link_text"))) 

Este caso de uso

Estás viendo NoSuchElementException porque el localizador de ID no identifica el canvas de forma única. Para identificar el canvas y click() en él, debe esperar a que se pueda clickable en el canvas y para lograr que pueda usar el siguiente bloque de código:

 WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//canvas[@id='window1']"))).click()