Web scraping con Java

Actualmente me encuentro desarrollando mi proyecto final de máster, el cual consiste en crear un modelo de aprendizaje automático que arroje predicciones acerca de partidos de futbol de la liga de primera división española. Para ello he necesitado entre otras cosas tener los resultados de todas las jornadas de las ultimas ligas. Aunque recientemente conseguí un paquete de R (enlace) que contenía los resultados desde 1929, este no me proporcionaba toda la información que yo buscaba, así que me decidí por obtener yo mismo esa información sacándola de las paginas deportivas y es lo que quiero compartir con ustedes.

En un principio pense en hacerlo en python con la biblioteca lxml, pero haciendo una búsqueda rápida por Internet encontré un proyecto en Java llamado Jsoup y debo decir que este si me simplifico la tarea.

Primero como todos saben es necesario que demos un repaso a la estructura del documento que vamos a scrapear y confirmar que hay un patron.

estructura documento html

Como pueden ver en la imagen, podemos detallar que todas las filas de las tablas de las jornadas comparten el atributo itemtype=»http://schema.org/SportEvent», así que este fue el que utilicé para obtener todas las filas y a partir de allí obtener los nombres de los equipos, el resultado y el enlace para ir al detalle del partido.

Par de cosas que quisiera comentar con respecto al código:

  • Podemos aplicar expresiones sobre elementos de antemano obtenidos, por ejemplo como se hizo para obtener los equipos que intervienen en el partido.
  • Existe otra forma además de la anteriormente explicada (usando expresiones) para obtener elementos del árbol DOM de la página Web, si damos un vistazo a la API de la biblioteca del partido, existe un método getElementsByAttributeValue, entonces para obtener el elemento score, este se pudo haber obtenido también de la siguiente manera

    Elements score = match.getElementsByAttributeValue(«class», «resultado resul_post»)

  • Por último si quisiéramos obtener mas datos por ejemplo del detalle del partido (ya que logramos obtener el url), esta biblioteca nos permite seguir navegando (haciendo conexiones), y sería cuestión de realizar otra conexión y de nuevo empezar a extraer elementos.
    Document detalleDelPartido = Jsoup.connect(statsLink).get()

Aquí les dejo el enlace al repositorio GitHub y espero que les pueda ser de utilidad.

Primer ejemplo con apache spark

Hace algunas semanas atrás que empezamos a trabajar con apache spark en el máster, brevemente les contare mis impresiones desde mi punto de vista como principiante.

Apache spark me gusto, ¿por qué? porque se puede programar en Scala (además de Python y Java),  la API de Scala lo simplifica mucho y la cantidad de código a teclear es (considerablemente) menor a la necesaria para hacer la misma tarea en Java, aunque aquí debo hacer un paréntesis, ya que con la entrada de Java 8 y las lambda expresión la cantidad de código será menor pero insisto la API de Scala a mi modo de ver lo hace mas sencillo.

Nos permite hacer operaciones con mucha data (quizás no Big Data, es decir no hablamos de TeraBytes) sin necesidad de usar Hadoop, me gustaría hacer hincapié en esto ya que muchos piensan que Big Data es Hadoop y NO, no es así, mi concepto de Big Data es un poco mas amplio y contempla mas cosas, aquí me refiero específicamente a la API MapReduce de Hadoop la cual es mas complicada de usar que la de Spark, no obstante si necesitamos trabajar con una cantidad de datos considerable que requiera del uso de HDFS, podemos desde Spark acceder a este sistema de archivo u algún otro como por ejemplo Amazon S3.

Por último decirles que Spark es mas rapido, esto se debe a su arquitectura, ya que este trabaja en memoria (todo en memoria si tiene la capacidad de cargar todos los datos por completo) y pues si llegamos a hacer varias tareas (lo que técnicamente sería reutilizar los RDD ya guardados en memoria) con los datos en memoria es cuando mas jugo se le sacará a Spark.

Sinceramente si alguien discrepa de mi o coincide me entusiasmaría mucho que comparta su opinión ya que todo este mundo que envuelve el Big Data me tiene super enganchado.

 Ahora bien vamos con los ejemplos, estas formaban parte de la primera tarea de Spark que tuvimos que realizar, y consiste en 2 ejemplos:

  1. Dado un fichero de texto en formato csv con información de medallistas olímpicos, obtener el numero de medallas por edad.
  2. Dado el mismo fichero de texto anterior, y un esquema de puntuación por tipo de medalla obtener un ranking de medallistas olímpicos.

He aqui el código:

 

Una última cosa que es bueno saber para aquellos que como yo están empezando con Spark y sus RDD, Los RDD tienen 2 tipos de operaciones: transformaciones y acciones, las primeras son operaciones que como resultado nos devuelven otro RDD y las acciones son aquellas que hacen «algo» sobre los datos como por ejemplo el foreach de mi código,  utilizado para mostrar por pantalla los valores finales, además los RDD (como hasta ahora lo entiendo) son las instrucciones a realizar sobre los datos, mas no almacenan la información, además estás instrucciones no se realizan de inmediato, sino que al contrario estos tienen un funcionamiento lazy, esto significa que se ejecutan cada vez que se realiza una operación de tipo acción.

Otra sugerencia, no duden en cacharrear con la consola de spark, de hecho el primer ejercicio lo llegue a hacer por la consola (sin los JavaBeans) y el practicar por aquí si que ayuda a conocer los operaciones a utilizar sobre los RDD.

Aquellos interesados en descargar el código, les dejo la dirección del ejercicio en mi repositorio github

El esqueleto del ejercicio esta en el repositorio del que fue nuestro profesor y pueden acceder a el haciendo clic aquí.

Cualquier material, idea o contenido que quieres compartir, no dudes en hacerlo, ya que bien recibido será. Ahora si para cerrar les dejo el enlace a un libro que hasta ahora me esta pareciendo muy bueno para aprender Spark (además con ejemplos elaborados en Java, Scala y Python).

Gephi una herramienta de visualización de redes

Esta semana en el Master empezamos con una nueva materia denominada «Análisis de redes sociales», el inicio ha sido bastante interesante, de hecho me pareció chévere, pero lo que quiero compartir con todos ustedes es la herramienta que vimos el primer día, esta se llama Gephi, es una herramienta open source hecha en Java para la visualización  de redes y pues nosotros empezamos analizando nuestra red social Facebook.

Visualización de mi red social Facebook

Visualización de mi red social Facebook

 Para que la herramienta funcione correctamente en Mac OSX hay que ser una serie de «trucos» y apaños (como ejecutarlo en Java 6) porque en caso contrario seremos incapaces de ni siquiera arrancar la aplicación. Aquí les dejo el enlace donde aparecen los pasos necesarios de configuración para poder ejecutarlo en Mac OSX.

La imagen de mas arriba es una perspectiva de todos los nodos que forman parte de mi red social Facebook. Para poder visualizar mi red de Facebook tuvimos que descargarnos un fichero de extensión .gml desde esta página donde podemos indicar que información queremos obtener de nuestra red de contactos, como sexo, lenguaje, entre otros.

Me gusto la herramienta no solo por lo versátil al momento de visualizar el diagrama y los resultados que obtuve (como las agrupaciones de nodos que son fácilmente identificables), sino porque tenia (y tengo) en mente hacer una visualización de mi red de Twitter, pero con Java y Neo4j, aunque ya compañeros del master me han hecho llegar un proyecto que genera el fichero .gml, por lo cual quizás visualice antes en Gephi mi red de Twitter. Sin mas dilación aquí les dejo el componente gigante de mi red donde señalo sus agrupaciones.

Componente gigante de mi red de Facebook

Componente gigante de mi red de Facebook

¿Alguno de ustedes ha hecho un análisis de alguna de sus redes sociales? ¿Que herramienta utilizaste? Si te animas a analizar alguna de tus redes sociales con Gephi, no dudes en compartir tu resultados con nosotros

Sabias que el uso de la annotation override nos advierte de errores en el código

Seguramente muchos de ustedes se habrán preguntado ¿que hace? o ¿para qué sirve esa @Override que nos coloca automáticamente el IDE al momento de implementar una interfaz? ¿Tendrá algún beneficio?.

Bueno para aquellos con esa interrogante les traigo la respuesta.

Pues si, si nos da un beneficio  cuando codificamos y consiste en advertirnos de posibles errores de lógica o compilación en los siguientes casos:

  • Cuando no estemos sobrescribiendo o implementando ningún método de la interfaz o superclase.
  • Cuando nos hemos equivocado en la firma del método a sobrescribir.

 Es por estos beneficios que deberíamos asumirlo (sobretodo aquellos que venimos de la vieja escuela de Java 1.1, 1.2 o 1.4) como una convención al momento de programar. Ahora bien vayamos a un ejemplo para ver de lo que estamos hablando.

EL siguiente código consta de una super clase la cual vamos a extenderla pero a propósito de este ejemplo sobrescribiremos erróneamente los métodos de la clase de tal forma que no coincidan en su firma con el original (el de la súper clase) o sencillamente no coincida el nombre del método, de tal forma de poder ver como al usar @Override, esta nos indica que hay algo mal, en nuestro código.

A continuación les dejo par de imágenes donde el IDE nos indica el error

IDE error al sobrescribir el método IDE error al sobrescribir el método

 

Como pudieron darse cuenta el Editor (en este caso eclipse), nos indica que hay un error en los métodos que estamos intentando sobrescribir.

Ya conocemos el significado de @Override y sus ventajas, ahora lo que resta es que hagamos uso de ella y lo asumamos como una buena practica de programación en Java.

Introducción a la clase Objects

Hace algunos meses atrás estudiando para la certificación de java 7, me entere de la existencia de la clase java.util.Objects, esta es una clase utilitaria compuesta en su totalidad de métodos estáticos que aunque lucen bastante simples, si que resultan de ayuda ahorrándonos algo de trabajo (tedioso), entre estos encontramos algunos para realizar comparaciones así como para el calculo del hash de un objeto, o también para evitar asignar null a objetos.

En este caso creo que no hay mejor forma que verlo en el código para que podamos apreciar su utilidad.

Si ejecutamos el main de esta clase obtendríamos el siguiente resultado

Además de los métodos utilizados existen un par más que son para calcular si dos (2) objetos son profundamente iguales y para realizar comparaciones.

¿Qué te ha parecido esta clase? ¿Ya la conocías? ¿La utilizas en tus desarrollos? y sino a que esperas.