Antes de escribir un rastreador web, es necesario comprender los datos que vas a extraer y cómo acceder a ellos. Hay muchas formas de acceder a los datos de una página web; la más habitual es utilizar selectores CSS. Otra alternativa es utilizar XPath. Puedes encontrar la hoja de referencia de XPath aquí.
Introducción al DOM
Durante el proceso de análisis de un archivo HTML, el navegador crea en su memoria una representación de los datos con forma de árbol. Esta representación se denomina DOM (Modelo de Objetos de Documento). Por cada etiqueta HTML, hay un nodo asociado a ella en el DOM. Un nodo tiene propiedades como nombre, contenido, nodos hijos, estilos, eventos, etc. Puedes encontrar más información sobre cómo funciona la renderización del navegador en este artículo: Cómo funciona la renderización del navegador: entre bastidores.
Cuando decimos que queremos acceder a los datos de una página web, lo que queremos es recorrer el DOM hasta un conjunto específico de nodos y extraer el contenido que hay en su interior. En este artículo te daré diferentes consejos sobre cómo acceder rápidamente a esos nodos utilizando selectores CSS.
¿Qué son los selectores CSS?
¿Por qué se llaman selectores CSS (hojas de estilo en cascada) en primer lugar?
El CSS se utiliza para definir la apariencia de los nodos en una página. Con el CSS puedes escribir reglas sobre cómo debe ser la apariencia de un nodo y cómo debe interactuar con otros nodos. Una regla se compone de un selector y una lista de estilos que se van a sobrescribir.
Por lo tanto, estos selectores se asocian con CSS porque ese es su uso más común, pero no es necesario utilizarlos solo con CSS. Con CSS, lo que se busca es seleccionar un nodo y cambiar su propiedad de estilo. Si lo piensas bien, queremos hacer lo mismo: seleccionar un nodo y hacer algo con él, como leer su contenido o activar un evento.
¿Cómo funcionan los selectores CSS?
Te resultará de gran ayuda visualizar cómo se produce la selección. Supongamos que quieres extraer todos los párrafos de un sitio web. Quieres obtener todos los nodos que tengan el nombre `p`. Puedes hacerlo a mano. Solo tienes que recorrer todos los nodos del DOM y seleccionar únicamente aquellos que tengan node.tagName === 'P' (los nombres de las etiquetas están en mayúsculas).
Aquí tienes un pequeño fragmento de código que puedes utilizar:
function scrapeByTagName(node, tagName) {
if (node === null)
return;
node.childNodes.forEach(node => {
//console.log(node.tagName)
if (node.tagName?.toLowerCase() === tagName.toLowerCase()) {
console.log(node)
return
}
scrapeByTagName(node, tagName)
});
}He creado una página web de prueba que tiene este aspecto:
Y este es el código HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="styles.css">
<script src="script.js"></script>
</head>
<body>
<div id="wrapper">
<h1 custom-attr="some data">Some Title</h1>
<h2 custom-attr="some other data">Some Subtitle</h2>
<div id="container">
<p custom-attr>paragraph
<span> subparagraph</span>
</p>
<p id="text">paragraph with id #text</p>
<p class="bold">paragraph with class .bold</p>
<p class="text">paragraph with class .text</p>
<p class="text bold">paragraph with class .text.bold</p>
<p class="text italic">paragraph with class .text.italic</p>
</div>
</div>
</body>
</html>Después de ejecutar la función en la consola del navegador, obtuve esta respuesta:
Como puedes ver, la función registró todas las etiquetas p.
Para ver la consola del navegador, tienes que abrir DevTools e ir a la pestaña «Consola» o pulsar la tecla Esc. Puedes abrir DevTools haciendo clic con el botón derecho en un elemento y seleccionando «Inspeccionar» en el menú, o utilizando el atajo de teclado Ctrl + Mayús + I.
¿Cómo se utilizan los selectores CSS?
Usaremos dos métodos: querySelector y querySelectorAll. Estos métodos están disponibles en todos los objetos de tipo Element. Los nodos que intentamos extraer son de tipo HTMLElement, que hereda del tipo Element.
querySelector devolverá el primer nodo que coincida con el selector. querySelectorAll devolverá una lista con todos los nodos que coincidan con el selector. Para replicar el ejemplo mostrado anteriormente, solo tenemos que llamar a querySelectorAll e iterar por la lista devuelta.
document.querySelectorAll('p').forEach(node => console.log(node))
Como puedes ver, he utilizado document.querySelectorAll; esto se debe a que document está definido en el contexto de la ventana como la raíz de la página web, es decir, el equivalente a la etiqueta html. Puedes utilizar los métodos querySelector con cualquier nodo, no solo con el nodo raíz.
Para extraer datos realmente, necesitarás utilizar una biblioteca que pueda abrir una ventana del navegador y acceder a una URL. Solo entonces se ejecutará tu código, en el contexto de esa ventana. Para saber más sobre cómo hacerlo, te recomiendo este artículo: «The Ultimate Guide to Web Scraping with JavaScript and Node.Js».
Aquí, en WebScrapingAPI, utilizamos Puppeteer. Puppeteer es una biblioteca que nos permite controlar instancias de navegadores Chromium sin interfaz gráfica. Puedes utilizar nuestra API para extraer datos de un sitio web sin necesidad de crear un rastreador personalizado. De hecho, contamos con un parámetro llamado extract_rules que utiliza selectores CSS para extraer datos de una URL determinada.
Hoja de referencia de selectores CSS
El selector *
Este selector especifica todos los elementos del árbol. No tiene mucho uso, pero es bueno conocerlo.
El selector .class
Puedes obtener un nodo con una clase específica utilizando .class. Se utiliza principalmente cuando tienes una lista de elementos. Dado que los elementos de una lista suelen tener el mismo aspecto, es probable que tengan la misma clase. Busquemos la clase .text.
Quizás quieras seleccionar el nodo que tiene la clase .bold.
Parece que hay otro elemento que tiene la clase .bold. Puedes ser más específico con el selector de clase utilizando varias clases concatenadas.
Ten en cuenta que no hay espacios entre las clases.
document.querySelectorAll('.text .bold').forEach(node => console.log(node))
Esta consulta no devuelve ningún resultado del HTML anterior, ya que busca un elemento con la clase .text que tenga un elemento secundario con la clase .bold (no necesariamente un elemento secundario directo). La consulta devolvería el elemento secundario si lo encontrara.
El selector #id
¿Qué ocurre si un elemento no tiene una clase o si la clase se utiliza con demasiada frecuencia en el documento? Puedes utilizar el atributo ID para lograr un mayor nivel de especificidad. El inconveniente de utilizar el selector id es que, en la mayoría de los casos, el id es único en la página HTML, por lo que no puedes obtener una lista de nodos con él.
El selector de nombre de nodo
Cada nodo tiene un nombre. Es el nombre exacto de la etiqueta emparejada en el HTML. Puedes obtener todos los nodos que tengan un nombre específico utilizando su nombre en el selector.
El selector [atributo]
Es posible que te encuentres con situaciones en las que quieras seleccionar todos los nodos que tengan algún atributo específico.
También puedes especificar el valor del atributo.
O incluso lo que debe contener el valor del atributo. Puedes usar la tilde ~ antes del signo igual para definir que el valor del atributo debe contener una lista de palabras.
El selector de atributos será el más utilizado si decides crear un scraper. Es muy potente y tiene muchos más casos de uso de los que he mostrado aquí. Puedes encontrar más información sobre cómo utilizar el selector de atributos aquí: Selectores de atributos W3.
Agrupación de múltiples selectores
Obtener todos los nodos p que tengan un id.
Seleccionar todos los nodos span que sean hijos de un nodo p.
Obtener todos los nodos div que sean hijos directos del nodo body.
Obtener todos los nodos p que tengan la clase .text
Las opciones para agrupar estos selectores son infinitas. Intenta copiar el código HTML de arriba y añádele más nodos. A continuación, prueba diferentes combinaciones de selectores. Si quieres aprender más sobre los selectores CSS en general, Mozilla ofrece un fantástico artículo que explica cómo funcionan los selectores CSS para el desarrollo web.
Resumen
Si quieres aprender algo nuevo, te aconsejo que primero aprendas cómo funciona. Sí, es un paso opcional, pero te proporcionará información que otros no tienen.
En el campo del desarrollo de software, esta información te ayudará a buscar la respuesta correcta a tu problema o error. Podrías tomar las riendas del asunto e incluso crear una solución personalizada.
Si realmente quieres entender los selectores CSS, necesitas entender el DOM. No es más que un árbol (un grafo acíclico no dirigido) con nodos que tienen un nombre y algunos atributos. Eso es todo. Cuando escribes un selector, simplemente escribes una cadena que se analiza y se utiliza para consultar el DOM.




