A logo showing the text blog.marcnuri.com
English
Inicio»Java»Quarkus + Picocli: Web scraper para extraer proyectos dependientes en GitHub

Entradas Recientes

  • Fabric8 Kubernetes Client 6.5.0 está disponible!
  • Fabric8 Kubernetes Client 6.4.1 está disponible!
  • Fabric8 Kubernetes Client 6.3.1 está disponible!
  • Eclipse JKube 1.10 está disponible!
  • Fabric8 Kubernetes Client 6.2.0 está disponible!

Categorías

  • Antiguo
  • Front-end
  • Herramientas
  • Java
  • JavaScript
  • Operaciones
  • Proyectos personales

Archivos

  • marzo 2023
  • enero 2023
  • diciembre 2022
  • noviembre 2022
  • octubre 2022
  • agosto 2022
  • julio 2022
  • mayo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • diciembre 2020
  • octubre 2020
  • agosto 2020
  • mayo 2020
  • marzo 2020
  • noviembre 2019
  • octubre 2019
  • julio 2019
  • diciembre 2018
  • agosto 2018
  • julio 2018
  • junio 2018
  • marzo 2018
  • febrero 2018
  • noviembre 2017
  • octubre 2017
  • agosto 2017
  • julio 2017
  • julio 2016
  • enero 2016
  • diciembre 2015
  • noviembre 2015
  • marzo 2007

Quarkus + Picocli: Web scraper para extraer proyectos dependientes en GitHub

2020-08-15 en Java etiquetado Cliente / GitHub / Java / JKube / Picocli / Quarkus por Marc Nuri | Última actualización: 2021-10-09
English version

Introducción

Durante los pasados meses, mi equipo y yo hemos estado trabajando muy duro para lanzar Eclipse JKube. JKube es el sucesor del ya obsoleto Fabric8 Maven Plugin, y como tal, nuestro principal objetivo ahora mismo es migrar aquellos proyectos que dependent de éste a JKube.

GitHub proporciona muchas estadísticas y métricas, entre ellas la información acerca del grafo de dependencias del proyecto. Esta información es muy valiosa, ya que podemos averiguar qué proyectos (dentro de GitHub) dependen del nuestro. Para nuestro caso de uso de migración de usuarios, esta información es exactamente lo que necesitamos. Desafortunadamente, la API para desarrolladores de GitHub proporciona información sobre dependencias, pero no sobre dependientes.

En este post os mostraré cómo crear un web scraper empleando Picocli y Quarkus para crear un nativo binario que rastreará las dependencias de cualquier proyecto en GitHub.

Nota: Antes de utilizar esta herramienta es muy importante asegurarse que cumples con las normas sobre restricciones de GitHub para el uso de su API y Scraping.

Estructurando la aplicación

El primer paso es iniciar el proyecto, para ello podemos emplear la interfaz de code.quarkus.io para generar un proyecto en blanco. En este caso, solo vamos a necesitar Picocli como dependencia (experimental). Por otro lado, también añadiremos jsoup como dependencia a nuestro pom.xml.

El propósito de la aplicación es rastrear la web de GitHub que está protegida mediante SSL, por ello es necesario que habilitemos el URL protocol https para el build de GraalVM. El plugin de Maven de Quarkus proporciona una forma muy sencilla de configurar esto mediante la inclusión de build arguments para que GraalVM los utilice.

1<!-- ... -->
2<build>
3  <plugins>
4    <plugin>
5      <groupId>io.quarkus</groupId>
6      <artifactId>quarkus-maven-plugin</artifactId>
7      <executions>
8        <execution>
9          <id>package</id>
10          <goals>
11            <goal>native-image</goal>
12          </goals>
13          <configuration>
14            <dockerBuild>${dockerBuild}</dockerBuild>
15            <additionalBuildArgs>
16              <additionalBuildArg>-H:EnableURLProtocols=https</additionalBuildArg>
17              <additionalBuildArg>-H:EnableURLProtocols=http</additionalBuildArg>
18            </additionalBuildArgs>
19          </configuration>
20        </execution>
21      </executions>
22    </plugin>
23  </plugins>
24</build>
25<!-- ... -->

Quarkus Command line application

A continuación, emplearemos Picocli para que nuestra aplicación sea amigable en la linea de comandos. Hay varias guías que nos ayudarán a conseguirlo, e incluso una sección completa del quarkus-cheat-sheet.

Application Main Class

Nuestra aplicación es muy sencilla y sólo require de un punto de entrada. Con el fin de hacer nuestro código más sencillo y legible, anotaremos nuestra main class con @CommandLine.Command. Este es el código fuente resultante:

1@CommandLine.Command(name = "github-dependents")
2public class Application implements Runnable {
3
4  private final ScraperService scraperService;
5
6  @CommandLine.Parameters(index = "0", paramLabel = "URL", arity = "1",
7    description = "GitHub URL to the projects dependents list")
8  String dependentsUrl;
9
10  @Inject
11  public Application(ScraperService scraperService) {
12    this.scraperService = scraperService;
13  }
14
15  @Override
16  public void run() {
17    try {
18      new URL(dependentsUrl);
19      scraperService.scrape(dependentsUrl);
20    } catch(MalformedURLException ex) {
21      System.err.printf("URL %s is invalid, please provide a valid URL.%n", dependentsUrl);
22      CommandLine.usage(this, System.out);
23    } catch (Exception e) {
24      System.err.println(e.getMessage());
25      e.printStackTrace();
26    }
27  }
28
29}

Teniendo en cuenta que quiero que la aplicación se pueda emplear para cualquier proyecto de GitHub, es necesario un parámetro de entrada para que el usuario pueda especificar que página quiere analizar. Bajo esta premisa, anotaré el campo dependentsUrl con @CommandLine.Parameters. Quiero destacar como Picocli tiene un claro objetivo de permitir que las aplicaciones sean muy amigables para el usuario y proporciona una seria de parámetros para permitir generar comandos de ayuda.

También emplearemos la anotación @Inject estándar de Java CDI proporcionada por Quarkus para inyectar la clase de servicio que se encargará de hacer el scraping.

Scraper Service

Esta clase contiene toda la lógica encargada de rastrear la página de dependientes en GitHub. La aplicación rastreará de forma recursiva las diferentes páginas devueltas por la consulta y devolverá una representación JSON de cada proyecto dependiente incluyendo la organización, el nombre, la URL, estrellas y forks de cada proyecto.

El servicio también se encarga de verificar que el input del usuario es correcto (URL válida, URL perteneciente a una página de dependientes, etc.). También incluye un algoritmo para reintentar y continuar con el rastreo en el caso en el que GitHub devuelva un HTTP status code 429 - Too Many Requests.

Ejecutando la aplicación

JVM

Para arrancar la aplicación empleando un Java Virtual Machine (JVM), primero necesitamos compilarla y empaquetarla:

1mvn clean package

Una vez hemos empaquetado la aplicación ya podemos ejecutarla para rastrear los dependientes de un proyecto:

1java -jar  target/github-dependents-scraper-uber.jar "https://github.com/eclipse/jkube/network/dependents?package_id=UGFja2FnZS0xMDY0ODYxMDkz"

Binario nativo

Para poder arrancar la aplicación empleando un nativo binario, primero tendremos que compilar, empaquetar y construir una imagen nativa de nuestra aplicación:

1mvn clean package -Pnative

Una vez el binario de nuestra aplicación esté listo, podemos ejecutarlo para rastrear los dependientes de un proyecto:

1./target/github-dependents-scraper-uber "https://github.com/eclipse/jkube/network/dependents?package_id=UGFja2FnZS0xMDY0ODYxMDkz"

El siguiente GIF muestra una demo de cómo utilizar la aplicación:

Una demo de la aplicación quarkus-picocli ejecutándose
Una demo de la aplicación quarkus-picocli ejecutándose

Conclusión

En este artículo os he mostrado como crear una aplicación de línea de comandos de manera muy sencilla empleando Quarkus y Picocli. Además hemos visto como crear un binario nativo de dicha aplicación sin ningún tipo de sufrimiento empleando las funcionalidades de Quarkus.

El código fuente completo de este post se encuentra en el repositorio de GitHub de github-dependents-scraper.

Quarkus
Quarkus
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Navegador de artículos

← Apache Camel y Casandra en un cluster KubernetesKubernetes Client for Java: Presentando YAKC →
© 2007 - 2023 Marc Nuri