Cómo extraer BoxScore FIBA Eurobasket en R
Función que extrae partidos jugados, limpios para usar y guardar en un csv. O no. Quién sabe.
📌 Este tutorial es gratis
Pues estos son los problemas técnicos a los que me refería en el notes, TODO funcionaba a las mil maravillas hasta que el lunes me dispongo a comprobar el código y
¡NO FUNCIONA!
Tenía la idea de compartir una función que extrajera todos los boxscores de la web oficial de FIBA desde su API. Pero mi gozo en un pozo: no todos los partidos tienen los datos bien cargados en el JSON.
¿Cómo conseguí el enlace de la API? NI pu.. idea. He intentado volver a encontrarlo… y nada, no ha habido forma.
Así que este post, que iba a ser uno de los más grandiosos, se ha quedado en un “podría haber sido”.
Aun así, creo que vale la pena compartir lo que sí funciona: cómo extraer los boxscores que sí están bien cargados, de los partidos ya jugados del Eurobasket… antes de que desaparezcan o acabe el campeonato.
O yo qué sé.
El viernes publiqué en X cómo el código antes devolvía 543 líneas y ahora apenas 378. En fin.
Lo que sí es cierto es que la API de FIBA devuelve un JSON mugroso, que hay que organizar un poco para poder usar.
👉 Este viernes, para suscriptores de pago, enseñaré cómo extraer el Play by Play y dejarlo limpio. Porque, seamos sinceros: los datos en crudo no hay dios que los entienda ni maneje.
Vamos directamente con la función. Tiene algunos detalles un poco enrevesados, así que iré comentando dentro del código.
Perdonad mi frustración (y el cabreo) que envuelve este post… pero no lo puedo disimular.
Lo de siempre: cargamos las librerías
library(tidyverse)
library(jsonlite)
library(httr)
library(janitor)
Paso 1: Creamos una función para extraer todos los ID de los partidos
home <- read_html("https://www.fiba.basketball/en/events/fiba-eurobasket-2025")
ids_tbl <- home %>%
html_elements("a[href*='/events/fiba-eurobasket-2025/games/']") %>%
html_attr("href") %>%
unique() %>%
as_tibble() %>%
rename(href = value) %>%
mutate(
id = str_match(href, "/games/(\\d+)-")[, 2], #extraemos el id
id = suppressWarnings(as.integer(id))
) %>%
pull(id) #esto selecciona la columna id y la crea sin formato
💡 Esta función extrae un total de 71 IDs, incluyendo partidos jugados y no jugados.
Paso 2: Función para extraer los boxscores
Esta función antes era más extensa (añadía más columnas y procesamiento), pero esto es lo que queda operativo:
fiba2 <- function(ids_tbl) {
url_api <- paste0("https://www.fiba.basketball/en/events/api/game-live-info/", ids_tbl, "/detail")
# Única descarga para mas rapidez
cnt <- url_api %>%
GET(query = list()) %>%
content()
if (rlang::is_empty(cnt$game$content$status) || cnt$game$content$status == "Unknown") {
return(tibble())
}
# tibble para chequear la url
statsPlayers <- cnt %>%
purrr::pluck("game", "content", 1)
# si es null devuelve un tibble vacio y si no, sigue con el siguiente #id
if (is.null(statsPlayers)) {
return(tibble())
}
#extrae las estadísticas del pártido
statsPlayersdf <- statsPlayers %>%
dplyr::tibble(value = .) %>%
unnest_wider(value, names_sep = "_") %>%
unnest_longer(value_Children) %>%
unnest_wider(value_Children) %>%
unnest_wider(Stats) %>%
select(where(~ !is.list(.)), -value_Nationality, -value_Code) %>%
remove_empty("cols") %>%
mutate(across(where(is.numeric), ~ replace_na(., 0))) %>%
mutate(
Id = as.numeric(str_extract(Id, "[0-9]+")),
id_match = ids_tbl, .before = 1
)
return(statsPlayersdf)
}
boxscoreFiba <- map_df(ids_tbl, fiba2)
#guardar en csv
write_csv(boxscoreFiba, "boxscoreFiba.csv")Y este es el resultado a dia 9/09/2025 a las 20:30, mañana quizás haya desaparecido toda la info….
En fin, como dijo el vaquero al Gran Lebowski:
“Unas veces te comes al oso… y otras el oso te come a ti.”
Gracias por el apoyo.






