¿Qué es el Web Scraping?

Web scraping es la técnica que se utiliza para extraer información de páginas web de forma automática. Consiste en leer el código de una página para obtener datos en bruto y transformarlos en datos estructurados que se pueden guardar en bases de datos u hojas de cálculo para analizar y extraer aquello que nos interesa.
Esta técnica se puede utilizar para recolectar datos de forma masiva con lo que podríamos decir que es parte de lo que conocemos como Big Data.

Según la Wikipedia, el web scraping también se puede utilizar para:

  • comparar precios en tiendas
  • monitorizar datos relacionados con el clima de cierta región
  • detectar cambios en sitios webs
  • integrar datos en sitios webs.

En mi caso más de una vez (y de dos) me he encontrado visitando la misma página varios días esperando un cambio, una actualización de información o una noticia que no acababa de llegar. Por eso se me ocurrió hace unos días crear un pequeño ejemplo de aplicación Java que hiciera este trabajo por mi.

La idea es que, sabiendo más o menos como se maqueta una web determinada y en qué URL se va a publicar la información que queremos, la aplicación detecte automáticamente cuando ocurre ese cambio y nos avise.

En este artículo solo voy a desarrollar el código de la aplicación (Lo puedes revisar o descargar completo desde aquí). La otra parte sería programar la ejecución de esta aplicación cuando a nosotros nos interese: al inicio de sesión, cada hora, cada 5 minutos o solo los viernes 13 a las 12 de la noche.
Si no sabes por donde empezar con esta tarea, aquí te dejo un artículo sobre cómo ejecutar programas al inicio de sesión en Linux con una pequeña introducción sobre como programarlos periódicamente con Cron.

Antes de empezar

Asumo que tienes unos conocimientos básicos de HTML. No hay que ser experto, pero si saber que existen etiquetas, clases, id’s y atributos y cómo utilizarlos.

Voy a utilizar una librería para extraer y manejar el código HTML. No es imprescindible, pero facilita mucho las cosas. He escogido Jsoup, pero cualquier otro parser HTML te puede servir.

Voy a proponer una situación ficticia en la que queremos comprobar todos los días si hay nuevos artículos en una tienda. Seguramente se te ocurran mejores utilidades para el web scraping, o te puede parece absurdo, porque tardamos menos en mirarlos por nuestra cuenta o directamente contactando con la tienda para que nos avise cuando tenga algo nuevo, pero como ejemplo nos va a servir.

Imaginemos que queremos observar una tienda online de ropa y queremos saber cuando hay nuevos abrigos. Para saber si hay nuevos artículos en algún momento, la primera vez tendremos que guardar lo que hay. Para hacerlo fácil, voy a escribir las descripciones de artículos y los enlaces en un documento txt que después utilizaré para hacer la comparación.

Al turrón

La URL para ver los abrigos es la siguiente (no los conozco, no penséis mal):

Ahora tenemos que pararnos un poco a analizar. Primero tenemos observamos cómo se forma la URL para cada página de artículos que pueda tener. En este caso simplemente añade -page2 al final:

Pero es habitual que se añadan parámetros para identificar la página y otras cosas, por ejemplo:

Aquí el parámetro que nos interesaría sería “pge”.

Ahora tenemos que identificar mediante ID’s o clases, las partes de la página que nos interesan.
Las páginas se suelen organizar en cajitas, que se definen con etiquetas <div > unas dentro de otras y normalmente hay una cajita que contiene todos los artículos que se muestran en la pantalla.
Para empezar a buscar nuestra caja maestra, basta con hacer click derecho encima de uno de los artículos y seleccionar “inspeccionar elemento”. Esto nos marcará dentro de una ventanita, el HTML el elemento que hemos seleccionado. Ahora vamos pasando el ratón por encima del código de otros elementos y vemos que nos lo señala en pantalla. Sabiendo que las cajas suelen estar anidadas, solo nos queda ir seleccionando una caja de nivel superior, hasta encontrar la que contiene todos los elementos que queremos observar.

recvisar-codigo-html

Cuidado con subir demasiado, porque puedes acabar seleccionando la etiqueta <body> que incluye todo lo que se ve en pantalla. No es que sea malo, pero vas a leer información de más y luego vas a tener que indagar más hasta que llegues a donde quieres realmente.

Volviendo al caso de los abrigos, el id de la caja que contiene todos los abrigos es id=”styleoverview” y tiene una forma parecida a esta:

Ya tenemos identificada la etiqueta y la URL. Empezamos con el código que va a leer la web

Al turrón, duro

Jsoup permite hacer peticiones HTTP y obtener el “status code” (404 no encontrado, 200 ok, etc…), así que comprobamos primero que la petición a nuestra URL funciona correctamente:

Necesitamos obtener el código de la web. Podemos hacerlo por nuestra cuenta, leyendo el html fila a fila con un bucle, o más fácil y rápido utilizando el siguiente método:

Así obtenemos el objeto Document con el dódigo HMTL completo con el que vamos a empezar a buscar y extraer información con los métodos de la librería Jsoup.
De todo el archivo HTML vamos haciendo nuestra selección. Recogemos el primer div que contenía todos los artículos:

Ahora recogemos todos los div con la clase “style”:

Y por último seleccionamos el texto que queríamos extraer en cada elemento:

Si no te convencen los selectores que he utilizado, en este enlace puedes ver como se utilizan por si quieres hacerlo de otra manera.

La variable “documentoProcesado” guarda el texto que queríamos extraer y que luego voy a a guardar en un archivo de texto.

Lo siguiente es guardar el contenido de esta variable en un documento de texto:

También tenemos que ver como podríamos leer el archivo de texto y compararlo. Recojo las lineas que sean diferentes en un ArrayList, para poder mostrar solo los nuevos abrigos:

Ya solo nos falta organizarlo todo. Aquí dejo el enlace al proyecto completo en Github para que veas una forma de hacerlo. Cualquier duda o sugerencia es bienvenida.

 

Fuentes:

Documentación de OracleDocumentación de Mozilla (para abrir nuevas pesatañas)
Mkyiong.com
Documentación de Jsoup
Jarroba (Los métodos getStatusConnectionCode y getHtmlDocument están cogido de este tutorial. Tienen un blog muy recomendable sobre programación)
Artículo sobre el tema en Wikipedia

Sobre El Autor

Economista reconvertido a programador. Hoy en día trabajo como Desarrollador de aplicaciones web y móvil con Node.js, Angular.js (MEAN Stack) e Ionic framework. También intento mantenerme al día de lo que se mueve en este mundillo y mantengo este pequeño blog como documentación personal. Si echas algo de menos en el blog no dudes en comentar, y si te ha resultado de utilidad algún artículo, te agradezco que lo agradezcas ;-). ¡Un saludo!

Artículos Relacionados

5 Respuestas

  1. Jorge

    Hola Eneko, soy algo novato en esto, y tengo una pregunta:
    El método que propones para obtener el HTML de una web Document doc = Jsoup.connect(url).get(); me devuelve el código fuente correctamente, pero el código que quiero obtener yo es el que se muestra cuando inspeccionas un elemento, y no el que se muestra cuando le das a “ver codigo fuente”. ¿Me explico?¿Cómo podría resolver esto? Muchas gracias

    Responder
    • Eneko

      Hola Jorge.
      Una vez que tienes todo el HTML tienes que ser capaz de identificar la parte que quieres extraer dentro del documento. Tienes que aprender a navegar por el DOM y localizar elementos por id, clase, hijos, etc…
      Entiendo que quieres extraer algo que está dentro de un div a secas. Lo explico en el párrafo que está encima de la foto, el que empieza con “Ahora tenemos que identificar mediante ID’s o clases…”.
      Si el div que quieres extraer tiene un atributo id, lo vas a tener fácil, será algo como esto:
      Element primerDiv = doc.getElementById(“idDelDiv”);
      También lo puedes identificar por clase, aunque si hay más de un elemento con esa clase te va a coger todos los que coincidan:
      Elements articulos = primerDiv.getElementsByClass(“claseDelDiv”);

      Aquí puedes mirar los selectores disponibles:

      Un saludo!

      Responder
  2. Jesús Alberto

    Hola Eneko.
    Estoy empezando con el tema de la Web Scraping y durante el proceso me surgio una duda al momento de tomar la evaluación de una página web.
    Quiero obtener valor de un span es algo así ::before ::after, pero lo que pude observar es que el número de la class=ranking_? va cambiando cuando son evaluaciones diferente.
    ¿Como puedo comparar el nombre del span para darle valor a una variable?

    Saludos…

    Responder

Hacer Comentario

Su dirección de correo electrónico no será publicada.