Web Scraping a la manera de Java

W

Introducción

Por definición, web scraping se refiere al proceso de extraer una cantidad significativa de información de un sitio web mediante scripts o programas. Dichos scripts o programas permiten extraer datos de un sitio web, almacenarlos y presentarlos como los diseñó el creador. Los datos recopilados también pueden ser parte de un proyecto más grande que utiliza los datos extraídos como entrada.

Anteriormente, para extraer datos de un sitio web, tenía que abrir manualmente el sitio web en un navegador y emplear la antigua pero dorada funcionalidad de copiar y pegar. Este método funciona, pero su principal inconveniente es que puede resultar agotador si la cantidad de sitios web es grande o si hay mucha información. Tampoco se puede automatizar.

Con web scraping, no solo puede automatizar el proceso, sino también escalar el proceso para manejar tantos sitios web como lo permitan sus recursos informáticos.

En esta publicación, exploraremos el web scraping utilizando el lenguaje Java. También espero que esté familiarizado con los conceptos básicos del lenguaje Java y tenga Java 8 instalado en su máquina.

¿Por qué Web Scraping?

El proceso de web scraping presenta varias ventajas que incluyen:

  • El tiempo necesario para extraer información de una fuente en particular se reduce significativamente en comparación con copiar y pegar los datos manualmente.
  • Los datos extraídos son más precisos y tienen un formato uniforme, lo que garantiza la coherencia.
  • Un raspador de banda se puede integrar en un sistema y alimentar datos directamente en el sistema mejorando la automatización.
  • Algunos sitios web y organizaciones no proporcionan API que proporcionen la información en sus sitios web. Las API facilitan la extracción de datos, ya que son fáciles de consumir desde otras aplicaciones. En su ausencia, podemos utilizar web scraping para extraer información.

El web scraping es ampliamente utilizado en la vida real por las organizaciones de las siguientes formas:

  • Los motores de búsqueda como Google y DuckDuckGo implementan el raspado web para indexar sitios web que finalmente aparecen en los resultados de búsqueda.
  • Los equipos de comunicación y marketing de algunas empresas utilizan scrapers para extraer información sobre sus organizaciones en Internet. Esto les ayuda a identificar su reputación en línea y trabajar para mejorarla.
  • El web scraping también se puede utilizar para mejorar el proceso de identificación y seguimiento de las últimas historias y tendencias en Internet.
  • Algunas organizaciones utilizan el web scraping para estudios de mercado donde extraen información sobre sus productos y también sobre sus competidores.

Estas son algunas de las formas en que se puede utilizar el web scraping y cómo puede afectar las operaciones de una organización.

Que utilizar

Hay varias herramientas y bibliotecas implementadas en Java, así como API externas, que podemos usar para construir web scrapers. El siguiente es un resumen de algunos de los más populares:

  • JSoup – esta es una biblioteca simple de código abierto que proporciona una funcionalidad muy conveniente para extraer y manipular datos mediante el uso de DOM transversal o selectores CSS para encontrar datos. No admite el análisis basado en XPath y es compatible con principiantes. Puede encontrar más información sobre el análisis de XPath Aquí.
  • HTMLUnit – es un marco más poderoso que puede permitirle simular eventos del navegador, como hacer clic y enviar formularios al raspar, y también tiene soporte para JavaScript. Esto mejora el proceso de automatización. También es compatible con el análisis basado en XPath, a diferencia de JSoup. También se puede utilizar para pruebas unitarias de aplicaciones web.
  • Excursión – esta es una biblioteca de automatización web y scraping que se puede usar para extraer datos de páginas HTML o cargas útiles de datos JSON mediante un navegador sin cabeza. Puede ejecutar y manejar solicitudes y respuestas HTTP individuales y también puede interactuar con API REST para extraer datos. Recientemente se ha actualizado para incluir compatibilidad con JavaScript.

Estas son solo algunas de las bibliotecas que puede utilizar para eliminar sitios web que utilizan el lenguaje Java. En esta publicación, trabajaremos con JSoup.

Implementación simple

Habiendo aprendido las ventajas, los casos de uso y algunas de las bibliotecas que podemos usar para lograr el raspado web con Java, implementemos un raspador simple usando la biblioteca JSoup. Vamos a eliminar este sencillo sitio web que encontré: CodeTriage que muestra proyectos de código abierto a los que puede contribuir en Github y que se pueden ordenar por idiomas.

Aunque hay API disponibles que brindan esta información, lo encuentro un buen ejemplo para aprender o practicar el raspado web.

Prerrequisitos

Antes de continuar, asegúrese de tener lo siguiente instalado en su computadora:

Vamos a utilizar Maven para gestionar nuestro proyecto en términos de generación, empaque, gestión de dependencias, pruebas entre otras operaciones.

Verifique que Maven esté instalado ejecutando el siguiente comando:

$ mvn --version

La salida debe ser similar a:

Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T21:33:14+03:00)
Maven home: /usr/local/Cellar/Maven/3.5.4/libexec
Java version: 1.8.0_171, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre
Default locale: en_KE, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.1", arch: "x86_64", family: "mac"

Preparar

Con Maven configurado correctamente, generemos nuestro proyecto ejecutando el siguiente comando:

$ mvn archetype:generate -DgroupId=com.codetriage.scraper -DartifactId=codetriagescraper -DarchetypeArtifactId=Maven-archetype-quickstart -DinteractiveMode=false
$ cd codetriagescraper

Esto generará el proyecto que contendrá nuestro raspador.

En la carpeta generada, hay un archivo llamado pom.xml que contiene detalles sobre nuestro proyecto y también las dependencias. Aquí es donde agregaremos la dependencia de JSoup y una configuración de plugin para permitir que Maven incluya las dependencias del proyecto en el archivo jar producido. También nos permitirá ejecutar el archivo jar usando java -jar mando.

Eliminar el dependencies sección en el pom.xml y reemplácelo con este fragmento, que actualiza las dependencias y las configuraciones del plugin:

  <dependencies>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
      </dependency>
     <!-- our scraping library -->
      <dependency>
          <groupId>org.jsoup</groupId>
          <artifactId>jsoup</artifactId>
          <version>1.11.3</version>
      </dependency>
  </dependencies>

  <build>
      <plugins>
          <!--
          This plugin configuration will enable Maven to include the project dependencies
          in the produced jar file.
          It also enables us to run the jar file using `java -jar command`
          -->
          <plugin>
              <groupId>org.apache.Maven.plugins</groupId>
              <artifactId>Maven-shade-plugin</artifactId>
              <version>3.2.0</version>
              <executions>
                  <execution>
                      <phase>package</phase>
                      <goals>
                          <goal>shade</goal>
                      </goals>
                      <configuration>
                          <transformers>
                              <transformer
                                      implementation="org.apache.Maven.plugins.shade.resource.ManifestResourceTransformer">
                                  <mainClass>com.codetriage.scraper.App</mainClass>
                              </transformer>
                          </transformers>
                      </configuration>
                  </execution>
              </executions>
          </plugin>
      </plugins>
  </build>

Verifiquemos nuestro trabajo hasta ahora ejecutando los siguientes comandos para compilar y ejecutar nuestro proyecto:

$ mvn package
$ java -jar target/codetriagescraper-1.0-SNAPSHOT.jar

El resultado debe ser Hello World! impreso en la consola. Estamos listos para comenzar a construir nuestro raspador.

Implementación

Antes de implementar nuestro scraper, necesitamos crear un perfil del sitio web que vamos a eliminar para ubicar los datos que pretendemos eliminar.

Para lograr esto, necesitamos abrir el CodeTriage sitio web y seleccione Java Language en un navegador e inspeccione el código HTML con las herramientas de desarrollo.

En Chrome, haga clic derecho en la página y seleccione “Inspeccionar” para abrir las herramientas de desarrollo.

El resultado debería verse así:

Como puede ver, podemos recorrer el HTML e identificar en qué parte del DOM se encuentra la lista de repositorios.

Desde el HTML, podemos ver que los repositorios están contenidos en una lista desordenada cuya clase es repo-list. En su interior están los elementos de la lista que contienen la información del repositorio que requerimos, como se puede ver en la siguiente captura de pantalla:

Cada repositorio está contenido en una entrada de elemento de lista cuyo class atributo es repo-item y la clase incluye una etiqueta de anclaje que contiene la información que necesitamos. Dentro de la etiqueta de anclaje, tenemos una sección de encabezado que contiene el nombre del repositorio y la cantidad de problemas. A esto le sigue una sección de párrafo que contiene la descripción y el nombre completo del repositorio. Esta es la información que necesitamos.

Construyamos ahora nuestro raspador para capturar esta información. Abre el App.java archivo que debería verse un poco así:

package com.codetriage.scraper;

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;


public class App {

  public static void main(String[] args) {
    System.out.println( "Hello World!" );
  }
}

En la parte superior del archivo, importamos IOException y algunas clases de JSoup que nos ayudarán a analizar los datos.

Para construir nuestro raspador, modificaremos nuestra función principal para manejar las tareas de raspado. Así que comencemos imprimiendo el título de la página web en el terminal usando el siguiente código:

  public static void main(String[] args) {
     try {
       // Here we create a document object and use JSoup to fetch the website
       Document doc = Jsoup.connect("https://www.codetriage.com/?language=Java").get();

       // With the document fetched, we use JSoup's title() method to fetch the title
       System.out.printf("Title: %sn", doc.title());

     // In case of any IO errors, we want the messages written to the console
     } catch (IOException e) {
       e.printStackTrace();
     }
  }

Guarde el archivo y ejecute el siguiente comando para probar lo que hemos escrito hasta ahora:

$ mvn package && java -jar target/codetriagescraper-1.0-SNAPSHOT.jar

La salida debe ser la siguiente:

Nuestro raspador está tomando forma y ahora podemos extraer más datos del sitio web.

Identificamos que los repositorios que necesitamos todos tienen un nombre de clase de repo-item, usaremos esto junto con JSoup getElementsByClass() función, para obtener todos los repositorios de la página.

Para cada elemento del repositorio, el nombre del repositorio está contenido en un elemento de encabezado que tiene el nombre de la clase repo-item-title, el número de problemas está contenido en un intervalo cuya clase es repo-item-issues. La descripción del repositorio está contenida en un elemento de párrafo cuya clase es repo-item-description, y el nombre completo que podemos usar para generar el enlace de Github cae dentro de un intervalo con la clase repo-item-full-name.

Usaremos la misma función getElementsByClass() para extraer la información anterior, pero el alcance estará dentro de un solo elemento del repositorio. Esa es mucha información de un tirón, así que describiré cada paso en los comentarios de la siguiente parte de nuestro programa. Volvemos a nuestro método principal y lo ampliamos de la siguiente manera:

 public static void main(String[] args) {
    try {
      // Here we create a document object and use JSoup to fetch the website
      Document doc = Jsoup.connect("https://www.codetriage.com/?language=Java").get();

      // With the document fetched, we use JSoup's title() method to fetch the title
      System.out.printf("Title: %sn", doc.title());

      // Get the list of repositories
      Elements repositories = doc.getElementsByClass("repo-item");

      /**
       * For each repository, extract the following information:
       * 1. Title
       * 2. Number of issues
       * 3. Description
       * 4. Full name on github
       */
      for (Element repository : repositories) {
        // Extract the title
        String repositoryTitle = repository.getElementsByClass("repo-item-title").text();

        // Extract the number of issues on the repository
        String repositoryIssues = repository.getElementsByClass("repo-item-issues").text();

        // Extract the description of the repository
        String repositoryDescription = repository.getElementsByClass("repo-item-description").text();

        // Get the full name of the repository
        String repositoryGithubName = repository.getElementsByClass("repo-item-full-name").text();

        // The reposiory full name contains brackets that we remove first before generating the valid Github link.
        String repositoryGithubLink = "https://github.com/" + repositoryGithubName.replaceAll("[()]", "");

        // Format and print the information to the console
        System.out.println(repositoryTitle + " - " + repositoryIssues);
        System.out.println("t" + repositoryDescription);
        System.out.println("t" + repositoryGithubLink);
        System.out.println("n");
      }

    // In case of any IO errors, we want the messages written to the console
    } catch (IOException e) {
      e.printStackTrace();
    }
}

Ahora compilemos y ejecutemos nuestro raspador mejorado con el mismo comando:

$ mvn package && java -jar target/codetriagescraper-1.0-SNAPSHOT.jar

La salida del programa debería verse así:

¡Si! Nuestro raspador funciona siguiendo la captura de pantalla de arriba. Hemos logrado escribir un programa simple que extraerá información de CodeTriage para nosotros y la imprimirá en nuestro terminal.

Por supuesto, este no es el lugar de descanso final para esta información, puede almacenarla en una base de datos y representarla en una aplicación u otro sitio web o incluso publicarla en una API para que se muestre en una extensión de Chrome. Las oportunidades son muchas y depende de usted decidir qué quiere hacer con los datos.

Conclusión

En esta publicación, hemos aprendido sobre el raspado web usando el lenguaje Java y hemos construido un raspador funcional usando la biblioteca JSoup simple pero poderosa.

Entonces, ahora que tenemos el raspador y los datos, ¿qué sigue? El web scraping es más de lo que hemos cubierto. Por ejemplo: llenado de formularios, simulación de eventos de usuario como hacer clic, y hay más bibliotecas que pueden ayudarlo a lograrlo. La práctica es tan importante como útil, así que cree más raspadores que cubran nuevos terrenos de complejidad con cada uno nuevo e incluso con diferentes bibliotecas para ampliar sus conocimientos. También puede integrar raspadores en sus proyectos existentes o nuevos.

El código fuente del raspador está disponible en Github para referencia.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad