Ir al contenido

Cómo seleccionar elementos por texto en XPath

Al raspar sitios web, a menudo es necesario seleccionar elementos de la página en función de su contenido de texto. Esto le permite apuntar con precisión a los datos que desea extraer. XPath, un lenguaje de consulta para seleccionar nodos en documentos XML y HTML, proporciona algunas formas de hacerlo utilizando el contains() y text() funciones.

En esta guía, analizaremos en profundidad cómo aprovechar estas técnicas de selección de texto en sus expresiones XPath. Cubriremos la sintaxis, analizaremos ejemplos y discutiremos algunas de las mejores prácticas para ayudarlo a seleccionar elementos de manera efectiva según su contenido de texto al realizar web scraping.

Usar contiene() para seleccionar elementos que contienen texto

El XPath contains() La función le permite seleccionar elementos que contienen una subcadena de texto específica. Se necesitan dos argumentos:

  1. Un conjunto de nodos para buscar dentro
  2. La subcadena de texto que debe coincidir

La sintaxis se parece a:

//element[contains(text(), "substring")]

Esto seleccionará todo element nodos cuyo contenido de texto contiene el especificado substring.

Por ejemplo, considere el siguiente HTML:

<ul>
  <li>Apples</li>
  <li>Oranges</li>
  <li>Pears and Grapes</li>
</ul>

Para seleccionar todo <li> elementos que contienen el texto "y", se utilizaría:

//li[contains(text(), "and")]

Esto coincidiría con el tercero. <li> elemento "Peras y Uvas".

El contains() La función distingue entre mayúsculas y minúsculas de forma predeterminada. Para realizar una coincidencia que no distinga entre mayúsculas y minúsculas, puede utilizar el lower-case() or upper-case() funciones para normalizar la carcasa:

//li[contains(lower-case(text()), "and")]

Una característica clave de contains() es que la coincidencia de subcadenas puede abarcar elementos secundarios. Por ejemplo, en este HTML:

<p>
  Select <em>this</em> paragraph.
</p>

El XPath //p[contains(text(), "Select this")] todavía coincidiría con el <p> etiqueta, aunque "Seleccionar" y "esto" están separados por la <em> elemento hijo.

Usando text() para seleccionar elementos por texto exacto

Aunque la contains() es útil para coincidencias de texto parciales, a veces es necesario hacer coincidir exactamente todo el contenido del texto. Aquí es donde el text() entra la función. Selecciona elementos en función de su contenido de texto completo.

La sintaxis es:

//element[text()="exact text"]

Por ejemplo, con este HTML:

<div>
  <p>Hello world!</p>
  <p>Hello again</p>
</div>

La expresión XPath //p[text()="Hello world!"] seleccionaría sólo el primero <p> elemento. El segundo <p> El elemento no coincide porque su contenido de texto no es exactamente "¡Hola mundo!".

Diferente a la contains(), la text() La función solo coincide con el contenido de texto directo de un elemento. No coincide con el texto dentro de los elementos secundarios. Por ejemplo, //div[text()="Hello world!"] no coincidiría con nada en el HTML anterior, porque el <div> en sí no contiene directamente el texto "¡Hola mundo!". Ese texto está dentro del <p> elemento hijo.

Me gusta contains(), la text() La función distingue entre mayúsculas y minúsculas de forma predeterminada. Lo mismo lower-case() or upper-case() Se puede utilizar una solución alternativa para coincidencias que no distinguen entre mayúsculas y minúsculas.

Combinar selectores de texto con otras expresiones XPath

Los selectores de texto se vuelven aún más poderosos cuando se combinan con otras partes de expresiones XPath, como nombres de etiquetas, atributos y selectores posicionales. Esto le permite crear selectores muy específicos para profundizar exactamente en los elementos que necesita.

Por ejemplo, podría utilizar el siguiente XPath para seleccionar <a> elementos que contienen la palabra "hacer clic" en el texto de su enlace, pero sólo si también tienen la clase "cta-button":

//a[contains(text(), "click") and @class="cta-button"]

O esta expresión para seleccionar el tercero. <p> elemento en la página, pero sólo si su contenido de texto comienza con "Introducción":

//p[starts-with(text(), "Introduction")][3]

Al mezclar y combinar diferentes construcciones XPath, puede crear selectores muy específicos para manejar casi cualquier escenario de web scraping.

Ejemplos de selector de texto con bibliotecas Python

Veamos algunos ejemplos prácticos del uso de selectores de texto XPath con bibliotecas de web scraping comunes de Python.

Ejemplo con lxml y solicitudes.

import requests
from lxml import html

# Send a GET request to the webpage
page = requests.get(‘https://example.com‘)

# Parse the HTML content
tree = html.fromstring(page.content)

# Select all <a> elements that contain the text "click me"
links = tree.xpath(‘//a[contains(text(), "click me")]‘)

# Print the href attribute of each selected link
for link in links:
    print(link.get(‘href‘))

Ejemplo con BeautifulSoup

import requests
from bs4 import BeautifulSoup

# Send a GET request to the webpage
page = requests.get(‘https://example.com‘)

# Parse the HTML content
soup = BeautifulSoup(page.content, ‘html.parser‘)

# Select the first <p> element that starts with the text "Introduction"
intro_para = soup.select_one(‘p[text^="Introduction"]‘)

print(intro_para.text)

Ejemplo con selenio

from selenium import webdriver
from selenium.webdriver.common.by import By

# Launch a browser and navigate to the webpage
driver = webdriver.Chrome()
driver.get(‘https://example.com‘)

# Select the <button> element with the exact text "Submit"
submit_button = driver.find_element(By.XPATH, ‘//button[text()="Submit"]‘)

submit_button.click()

Sugerencias y mejores prácticas

Cuando utilice selectores de texto XPath para web scraping, tenga en cuenta estos consejos:

  1. Tenga en cuenta los espacios en blanco en el texto que intenta hacer coincidir. Los espacios adicionales o los caracteres de nueva línea pueden hacer que sus selectores fallen. Utilice normalize-space() para eliminar los espacios en blanco iniciales y finales y contraer los espacios en blanco internos si es necesario.

  2. Preste atención a las mayúsculas. De forma predeterminada, la coincidencia de texto en XPath distingue entre mayúsculas y minúsculas. Utilice minúsculas() o mayúsculas() para coincidencias que no distingan entre mayúsculas y minúsculas.

  3. Evite selectores de texto demasiado generales, ya que pueden coincidir con elementos no deseados. Intente combinar selectores de texto con nombres de elementos o atributos para hacerlos más específicos.

  4. Pruebe siempre sus selectores con el contenido real y actual de la página. Los sitios web cambian con frecuencia, por lo que los selectores que funcionaron ayer podrían fallar hoy si se actualiza el contenido del texto.

  5. Si un sitio web tiene un formato inconsistente o contenido generado por el usuario, los selectores de texto pueden no ser confiables. En estos casos, suele ser mejor utilizar selectores estructurales basados ​​en los nombres de los elementos, los atributos o la posición en el árbol del documento.

Conclusión

XPath proporciona formas potentes de seleccionar elementos según su contenido de texto, utilizando el contains() y text() funciones. contains() es útil para hacer coincidir elementos que contienen una subcadena de texto específica, mientras que text() selecciona elementos por su contenido exacto de texto completo.

Estos selectores de texto son aún más efectivos cuando se combinan con otras expresiones XPath para crear selectores de elementos altamente específicos para web scraping.

Más allá de contains() y text(), XPath tiene otras funciones útiles para trabajar con texto, como starts-with(), ends-with(), normalize-space(), y más. Invierta algo de tiempo en aprender estas y otras partes clave de la sintaxis XPath.

Con un conocimiento sólido de los selectores de texto XPath, estará en el buen camino para poder seleccionar y extraer con precisión los datos que necesita de las páginas web. ¡Feliz raspado!

Únase a la conversación

Su dirección de correo electrónico no será publicada. Las areas obligatorias están marcadas como requeridas *