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.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.josedeveloper.WebScrapingExample; 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 ) throws IOException { final String url = "http://resultados.as.com/resultados/futbol/primera/2014_2015/calendario"; Document doc = Jsoup.connect(url).get(); //Obtenemos todas las filas identificadas como evento deportivo //ya que con este atributo es como se identifican los partidos Elements matches = doc.select("tr[itemtype$=\"http://schema.org/SportsEvent\"]"); for (Element match: matches) { //Obtenemos los equipos de cada partido utilizando también expresiones Elements teams = match.select("td[itemtype$=\"http://schema.org/SportsTeam\"]"); //obtenemos el enlace al detalle del partido Elements score = match.select("a[class=\"resultado resul_post\"]"); String localTeam = teams.get(0).text(); String visitorTeam = teams.get(1).text(); String statsLink = score.first().attr("href"); String[] goals = score.first().text().split("-"); int localGoals = Integer.parseInt(goals[0].trim()); int visitorGoals = Integer.parseInt(goals[1].trim()); System.out.println(localTeam + " vs " + visitorTeam + ": " + localGoals + "-" + visitorGoals + " -> " + statsLink); } } } |
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.