Extracción de los presupuestos de la Universidad de Oviedo 2025. Parte 01.
Extracción de los presupuestos de la Universidad de Oviedo 2025
La Universidad de Oviedo publica sus presupuestos anuales en el Boletín Oficial del Principado de Asturias. Este boletín ha presentado los presupuestos, más de 300 páginas, en un fichero informático pdf que no permite copiar el texto ni realizar búsquedas informáticas en el mismo. Desconozco los motivos para presentar esta información de esta forma y tal vez los responsables de este servicio público poseen poderosas razones para impedir que un usuario normal emplee las propiedades de búsqueda y copia de un fichero pdf.
Afortunadamente, la Universidad de Oviedo publica dicha información en su portal de transparencia y basta esperar unos días para consultarlo de forma amena.
Sin embargo, me ha picado la curiosidad de cómo se pudiera extraer la información contenida en el boletín. El primer paso consiste en emplear un programa de reconocimiento de caracteres para procesar el texto contenido en ese documento.
Conversión a png
Convertimos cada página en una imagen de tipo png con buena resolución (1200).
pdftoppm -r 1200 -png 2024-11360.pdf png/presupuesto
Reconocimiento de caracteres
Para cada imagen, que se corresponde a cada página, la procesamos con tesseract
con las opciones de lengua española y que almacene las posiciones de cada palabra.
# Perform OCR on each image and save as text files for img in png/presupuesto-*.png; do tesseract "$img" "${img%.png}" -l spa -c tessedit_create_tsv=1 done
El archivo TSV (Tab-Separated Values) generado por Tesseract contiene la siguiente información sobre el texto reconocido en la imagen:
Columna | Descripción |
---|---|
level | Nivel jerárquico del elemento reconocido: |
- 1: Página | |
- 2: Bloque (región rectangular de texto dentro de la página) | |
- 3: Párrafo (dentro de un bloque) | |
- 4: Línea (dentro de un párrafo) | |
- 5: Palabra (dentro de una línea) | |
pagenum | Número de la página en la que se encuentra el elemento (para documentos multipágina). |
blocknum | Número del bloque dentro de la página. |
parnum | Número del párrafo dentro del bloque. |
linenum | Número de la línea dentro del párrafo. |
wordnum | Número de la palabra dentro de la línea. |
left | Coordenada X del borde izquierdo del elemento (en píxeles). |
top | Coordenada Y del borde superior del elemento (en píxeles). |
width | Ancho del elemento (en píxeles). |
height | Alto del elemento (en píxeles). |
conf | Nivel de confianza del reconocimiento (porcentaje). Un valor más alto indica mayor certeza. |
text | El texto reconocido para el elemento correspondiente. |
Agrupamos los ficheros de extracción de texto
Leemos todos los ficheros anteriores, actualizamos el número de página y guardamos todo en una base de datos.
library(data.table);setDTthreads(0L); file_list <- list.files(path="png",pattern = "presupuesto-\\d{3}\\.tsv") ldd <- lapply(file_list,function(file){ cat(file,"\n") ## Extract the page number from the filename (e.g., "page-001.tsv" -> 1) page_number <- as.integer(gsub("presupuesto-(\\d{3})\\.tsv", "\\1", file)) ## Read the data dd <- fread(file.path(path="png",file),quote="") ## Change the number dd[, page_num:= page_number] dd }) datos <- rbindlist(ldd) fwrite(datos,"extraccion.csv")
Ya está disponible la base de datos primaria. Los pasos aquí descritos sirven más o menos para procesar documentos en pdf de los que no se pueda extraer la información. A partir de ahora toca adaptar el estudio a cada situación en particular.