¿Cómo encuentro un elemento que contiene texto específico en Selenium WebDriver (Python)?
Estoy intentando probar una interfaz JavaScript complicada con Selenium (usando la interfaz Python y en varios navegadores). Tengo varios botones del formulario:
<div>My Button</div>
Me gustaría poder buscar botones basados en "Mi botón" (o coincidencias parciales que no distinguen entre mayúsculas y minúsculas, como "mi botón" o "botón").
Esto me resulta increíblemente difícil, hasta el punto de que siento que me estoy perdiendo algo obvio. Lo mejor que tengo hasta ahora es:
driver.find_elements_by_xpath('//div[contains(text(), "' + text + '")]')
Sin embargo, esto distingue entre mayúsculas y minúsculas. La otra cosa que probé es recorrer todos los divs de la página y verificar la propiedad element.text. Sin embargo, cada vez que obtienes una situación de la forma:
<div class="outer"><div class="inner">My Button</div></div>
div.outer también tiene "Mi botón" como texto. Para solucionarlo , intenté ver si div.outer es el padre de div.inner, pero no pude descubrir cómo hacerlo (element.get_element_by_xpath('..') devuelve el padre de un elemento, pero prueba que no es igual a div.outer).
Además, la iteración a través de todos los elementos de la página parece ser muy lenta, al menos usando el controlador web Chrome.
¿Ideas?
Pregunté (y respondí) una versión más específica aquí: ¿Cómo puedo obtener el texto de un elemento en Selenium WebDriver, sin incluir el texto del elemento secundario?
Pruebe lo siguiente:
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
En el HTML que ha proporcionado:
<div>My Button</div>
El texto My Button
es el innerHTML
y no tiene espacios en blanco alrededor, por lo que puede usarlo fácilmente text()
de la siguiente manera:
my_element = driver.find_element_by_xpath("//div[text()='My Button']")
Nota :
text()
selecciona todos los nodos de texto secundarios del nodo de contexto.
Texto con espacios iniciales/finales
En caso de que el texto relevante contenga espacios en blanco al principio:
<div> My Button</div>
o al final:
<div>My Button </div>
o en ambos extremos:
<div> My Button </div>
En estos casos tienes dos opciones:
Puede utilizar
contains()
la función que determina si la cadena del primer argumento contiene la cadena del segundo argumento y devuelve un valor booleano verdadero o falso de la siguiente manera:my_element = driver.find_element_by_xpath("//div[contains(., 'My Button')]")
Puede utilizar
normalize-space()
una función que elimina los espacios en blanco iniciales y finales de una cadena, reemplaza secuencias de caracteres de espacios en blanco por un solo espacio y devuelve la cadena resultante de la siguiente manera:driver.find_element_by_xpath("//div[normalize-space()='My Button']")
Expresión XPath para texto variable
En caso de que el texto sea una variable, puedes usar:
foo= "foo_bar"
my_element = driver.find_element_by_xpath("//div[.='" + foo + "']")
Podrías probar una expresión XPath como:
'//div[contains(text(), "{0}") and @class="inner"]'.format(text)
//* buscará cualquier etiqueta HTML. Donde, si algún texto es común para el botón y la etiqueta div y si //* son categorías, no funcionará como se esperaba. Si necesita seleccionar algo específico, puede obtenerlo declarando la etiqueta del elemento HTML. Como:
driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")