¿Cómo se utiliza EC.presence_of_element_located((By.ID, "myDynamicElement")) excepto para especificar la clase, no el ID?

Resuelto Rishi Vadaga asked hace 5 años • 5 respuestas

Estoy intentando usar Python para raspar un sitio web que carga su HTML dinámicamente mediante el uso de archivos javascript incrustados que representan los datos como una respuesta en el HTML. Por lo tanto, si uso BeautifulSoup solo, no podré recuperar los datos que necesito ya que mi programa los eliminará antes de que Javascript los cargue. Debido a esto, estoy integrando la biblioteca de selenio en mi código, para hacer que mi programa espere hasta que se encuentre cierto elemento antes de eliminar el sitio web.

Originalmente había hecho esto:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.ID, "tabla_evolucion")))

Pero quiero especificar una clase haciendo algo como:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.class, "ng-binding ng-scope")))  

Aquí está el resto de mi código:

driver_path = 'C:/webDrivers/chromedriver.exe'
driver = webdriver.Chrome(executable_path=driver_path)
driver.header_overrides = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'}
url = "myurlthatIamscraping.com" 
response = driver.get(url)
html = driver.page_source
characters = len(html)
element = WebDriverWait(driver,100).until(EC.presence_of_element_located((By.class, "ng-binding ng-scope")))

print(html)
print(characters)
time.sleep(10)
driver.quit()

No me funciona y no encuentro la sintaxis correcta en ningún lado.

Rishi Vadaga avatar Jul 30 '19 05:07 Rishi Vadaga
Aceptado

El HTML relevante nos habría ayudado a construir una respuesta más canónica. Sin embargo, para comenzar con la primera línea de código:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located(
  (By.ID, "tabla_evolucion")))

es bastante legítimo donde la segunda línea de código:

element = WebDriverWait(driver,100).until(EC.presence_of_element_located(
  (By.class, "ng-binding ng-scope")))

Generará un error como:

Mensaje: selector no válido: nombres de clases compuestas no permitidas

ya que no puedes pasar varias clases By.class.

Puede encontrar una discusión detallada en Selector no válido: nombres de clases compuestos no permitidos usando find_element_by_class_name con Webdriver y Python


Solución

Debes ocuparte de un par de cosas de la siguiente manera:

  • Sin ninguna visibilidad de su caso de uso, inducir funcionalmente WebDriverWait en asociación con EC simplemente presence_of_element_located()confirma la presencia del elemento dentro del árbol DOM . Presumiblemente, para seguir adelante necesita obtener los atributos, por ejemplo value, innerTextetc., o interactuaría con el elemento. Entonces, en lugar de presence_of_element_located()usar cualquiera de los visibility_of_element_located()dos oelement_to_be_clickable()

Puede encontrar una discusión detallada en WebDriverWait que no funciona como se esperaba.

  • Para obtener un resultado óptimo, puede agrupar los atributos IDy CLASS y puede utilizar cualquiera de las siguientes estrategias de localización :

  • Usando CSS_SELECTOR:

  element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located(
    (By.CSS_SELECTOR, ".ng-binding.ng-scope#tabla_evolucion")))
  • Usando XPATH:
  element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located(
    (By.XPATH, "//*[@class='ng-binding ng-scope' and @id='tabla_evolucion']")))
undetected Selenium avatar Aug 01 '2019 17:08 undetected Selenium

Está en los documentos .

Conjunto de estrategias de localización soportadas.
CLASS_NAME = 'nombre de clase'
CSS_SELECTOR = 'selector css'
ID = 'id'
LINK_TEXT = 'texto de enlace'
NAME = 'nombre'
PARTIAL_LINK_TEXT = 'texto de enlace parcial'
TAG_NAME = 'nombre de etiqueta'
XPATH = 'xpath'

Nota: Lo que tienes en tu código no es una clase, son dos clases. Eso no funcionará si lo usa By.CLASS_NAME()porque solo espera una clase. Lo que quieres en su lugar es un selector de CSS.

EC.presence_of_element_located((By.CSS_SELECTOR, ".ng-binding.ng-scope")))

En la sintaxis del selector CSS, a .indica una clase. Consulte los documentos del W3C para obtener más información sobre la sintaxis del selector de CSS.

JeffC avatar Jul 30 '2019 02:07 JeffC