Mostrando entradas con la etiqueta Camelot. Mostrar todas las entradas
Mostrando entradas con la etiqueta Camelot. Mostrar todas las entradas

miércoles, 24 de septiembre de 2025

Datos. Python.

Biblioteca Camelot (III)

Conversión de tablas a Excel




Para finalizar esta serie de entradas sobre Camelot, expongo en esta entrada la transcripción del script del autor de [ExcelMasPro] cuyo vídeo cité como fuente [en esta entrada]. Sirva de agradecimiento a su autor.


El objetivo de esta entrada es triple: reconocer lo que ExcelMasPro nos aporta con su trabajo, mostrar otro modo de trabajar con Python y retomar la referencia a la relación entre este lenguaje y las hojas de cálculo. Y todo en el mismo paquete.

Paso sin más a presentar el script que he escrito copiando literalmente el que se expone en el vídeo, aunque el que aquí presento omite la formulación de la función y la llamada a la misma. Esto no altera el propio funcionamiento del código, aunque lo simplifica adaptándolo al modo de trabajar que se ajusta a mi nivel actual de conocimiento:

import camelot
import os
import pandas as pd
from tkinter import Tk
from tkinter.filedialog import askopenfilename, askdirectory
from datetime import datetime

#Ocultar ventana principal de TKinter
Tk().withdraw()

#Seleccionamos el archivo pdf
print("Seleccione el archivo PDF:")
pdf_file = askopenfilename(
    title = "Seleccionar el archivo PDF",
    filetypes=[("Archivos PDF","*.pdf")]
    )
if not pdf_file:
    print("No se seleccionó ningún archivo. Saliendo...")

#Seleccionar la carpeta de destino
print("Seleccione la carpeta donde desea guardar el archivo Excel:")
output_folder = askdirectory(title="Seleccionar carpeta de destino")
if not output_folder:
    print("No se seleccionó ninguna carpeta. Saliendo...")
    
#Nombrar el archivo Excel
now = datetime.now().strftime("%m-%d-%y-%H-%M")
output_excel = os.path.join(output_folder, f'Import_PDF_a_Excel_{now}.xlsx')

#Extracción de las tablas del pdf mediante Camelot
print("Extrayendo tablas del PDF...")
tables = camelot.read_pdf(pdf_file,pages="all", flavor="stream")

#Guardar las tablas en Excel
if not tables:
    print("No se encontraron tablas en el archivo PDF:")

#Guardando las tablas
with pd.ExcelWriter(output_excel, engine="openpyxl") as write:
    for i, table in enumerate(tables):
        table.df.to_excel(write, sheet_name = f'Tabla_{i+1}', index=False)

En resumen, lo que hace este script es acceder a un archivo pdf, capturar las tablas que incluye (lo que Camelot identifica como tales, que no siempre lo son) y copiarlas en una hoja de cálculo en la que crea tantas hojas como tablas encuentra.

El uso de TKinter permite al script facilitar una entrada de datos personalizada y en formato gráfico; cosa que raramente he empleado yo por considerarlo innecesario en este nivel de aprendizaje, pero en este caso me ha parecido interesante mantenerlo por mostrar otras formas de trabajar con Python (más cercanas al desarrollo de aplicaciones o DocAp).

Me ha parecido especialmente interesante el modo de construir el nombre del documento Excel creado, aunque he realizado un pequeño cambio en el formato (uniendo todos los elementos mediante guion bajo).

Realmente este script es más que una forma de mostrar el uso de Camelot (o de TKinter), incluyendo el procedimiento de crear y guardar datos en una hoja de cálculo de Excel. Supone poner a nuestra disposición una pequeña aplicación que nos resuelve el problema de acceder a cualquier documento pdf y extraer las tablas que contenga dejándonoslas disponibles como documento Excel. No siempre funciona perfectamente (sobre todo cuando los documentos son complejos) y no siempre extrae todos los datos de las tablas (interesa comprobar la calidad del resultado), pero al menos para pdf sencillo y tablas "normales" el éxito está garantizado.


Datos. Python.


Biblioteca Camelot (II)

Extracción de tablas en pdf complejos



Aunque se trate de una forma bastante simple de entender la complejidad, cuando manejamos un pdf con varias tablas y/o con varias páginas, la cosa cambia. Ya no nos sirven procedimientos tan simples como el utilizado en la [entrada anterior].


Es cierto que esta mayor complejidad es relativa, pero lo es suficientemente como para que necesitemos formular script con Camelot diferentes del anterior. Aprovecharemos también esta entrada para variar un poco de objetivo, buscando ahora guardar nuestras tablas en un documento externo.

import camelot

# Especifica la ruta al archivo PDF
file_path = 'tablaSimple_c.pdf' 

# Usa el método lattice para extraer tablas
tables = camelot.read_pdf(file_path, flavor= 'lattice' , pages= '1-end' )

# Guarda las tablas en formato CSV
tables.export( 'tablas.csv' , f= 'csv' , compress= True ) 

# Imprime el contenido de todas las tablas 
for i, table in  enumerate (tables): 
    print ( f"Table {i + 1 } " ) # Numera la tabla
    print (table.df) #Y la imprime en consola 

El documento pdf con el que trabajamos en este caso está dividido en tres hojas y cada una de ellas contiene una tabla sencilla. El procedimiento, según se observa en el script, es, sin embargo un tanto diferente.

Ahora no es suficiente con indicar en el método camelot.read_pdf() como único parámetro la ruta del archivo (file_path), también es necesario establecer el número de páginas a estudiar (pages= '1-end') y el método empleado para extraer las tablas (flavor= 'lattice'). Veamos ambos parámetros con más detalle.

Cuando un documento tiene una única página, la función camelot.read_pdf() no precisa que se especifique el parámetro pages ya que asume por defecto esa condición, pero si omitimos el parámetro cuando el documento tiene más de una página, no se produce error, pero el script sólo trabaja con la primera página del documento y devuelve únicamente las tablas que contenga la página 1 del documento.

Por el contrario, si conocemos el documento y sabemos en qué páginas contiene tablas y en cuales no, usando el identificador de páginas de forma selectiva no ahorramos obtener datos que no nos interesan, ya que Camelot puede interpretar como tablas segmentos del documento que no lo son. Por ejemplo, si el parámetro  pages se concreta como pages= '1-end', el script registra las tablas de las hojas 1 al final del documento, lo que equivale a  pages= 'all' (todas las hojas); pero sí especifico  pages= '1-2' sólo trabajará con el intervalo de hojas 1 a 2 y si solicitamos  pages= '1,3' lo hará con las tablas de las hojas 1 y 3. También son posibles combinaciones de página e intervalo, como por ejemplo  pages= '1-5,4,7,12-end'.

Respecto al método de extracción de tablas, latice está diseñado para extraer tablas de contornos bien definidos, mientras que su alternativa (stream), más lento, permite trabajar con tablas de límites mal definidos y celdas separadas por espacios.

Este parámetro (flavor) no es necesario cuando las tablas son el contenido único de la página y además están bien definidas, pero sí lo son cuando el documento presenta mayor complejidad. Aunque no siempre incluirlo mejora los resultados.

El siguiente paso consiste en generar un archivo (en este caso uno por tabla y en formato csv) para guardar el resultado de la extracción, lo que en este caso conseguimos con la función export() (tables.export( 'tablas.csv' , f= 'csv' , compress= True ) ), donde especificamos el nombre del archivo ('tablas.csv'), el tipo de archivo (f= 'csv') y si se presentan comprimidos o no (compress= True). El resultado es una carpeta comprimida que contiene (en mi caso) tres documentos csv, cada uno con su correspondiente tabla.

Finalmente podemos imprimir por consola (Shell en realidad) cada una de esas tablas, cosa que ahora implica hacer uso de un bucle (for i, table in  enumerate (tables):) que escribe por pantalla el número de la tabla (según su posición en el texto) (print ( f"Table {i + 1 } " )) y su contenido (print (table.df)). El resultado de esta parte del script es la escritura en consola de las tres tablas de forma consecutiva. Podríamos optar por acceder a cualquiera de ellas sustituyendo el ciclo por una instrucción simplificada de escritura (vg. print(tables[0].df))

Bueno, pues en esta entrada hemos aprendido unas cuantas cosas más. Especialmente interesante poder guardar las tablas extraídas en un documento de fácil acceso y manejo.

martes, 23 de septiembre de 2025

Datos. Python



Biblioteca Camelot (I)

Extracción de tablas en pdf





Cuando trabajamos con documentos pdf, uno de los contenidos de especial interés y que además resulta especialmente complicado de manejar son las tablas de datos (1). Para acceder a su contenido podemos emplear recursos como PyPDF2, pero el resultado no es muy satisfactorio como hemos tenido ocasión de comprobar, así que deberemos probar con otros medios.


Realmente es complicado automatizar la extracción de datos desde un documento pdf de forma realmente útil y son precisamente las tablas las que mayor dificultad presentan (2). Camelot es una librería pensada específicamente para esta tarea y funciona satisfactoriamente, al menos con tablas reales (no con imágenes incrustadas en el pdf) y de conformación sencilla.

Cierto es que trabajar con Camelot presenta cierta dificultad, incluyendo algunas complicaciones para su instalación, pero si empezamos por el principio se pueden superar. Por eso te recomiendo que conozcas esta biblioteca por sus fuentes [web del proyecto], incluyendo la lectura de su [manual on-line] (3).

También supone empezar por el principio planteándote metas sencillas y trabajando con pdf también sencillos. Podrás ir incrementando la complejidad conformes vayas dominando la herramienta. 

Yo te voy a mostrar ahora la que es posiblemente la forma más sencilla de abordar el problema también más simple: mostrar en pantalla el contenido de una tabla de un documento pdf simple (de una página) que contiene una tabla también simple. Inmediatamente podremos pasar a cuestiones de mayor complejidad.

Supongamos que ese documento pdf (tablaSimple.pdf) contiene esta tabla...


... a la que deseamos acceder desde un script de Python (4), concretamente desde este...

import camelot

# Especifica la ruta al archivo PDF
file_path = 'tablaSimple.pdf' 

# Lee las tablas del PDF
tables = camelot.read_pdf(file_path) 

# Imprime el número de tablas encontradas 
print ( f"Total de tablas encontradas: {tables.n} " ) 

# Imprime el contenido de la primera tabla 
print (tables[ 0 ].df)

... que nos devuelve esa misma tabla en el IDE Shell (en mi caso)


Vistas así las cosas, la verdad es que este logro parece bastante pobre, pero podemos hacer varias cosas a partir de aquí; entre otras pasar la tabla a un archivo Excel o de otra extensión (5) o trabajar directamente con el contenido de la tabla mediante librerías como Pandas (6).

En este caso vamos a importar la librería pandas (sin entrar ahora en más detalle)

import pandas as pd

... y añadir unas cuantas instrucciones más al script, por ejemplo acceder a la tabla capturada y pasar a una colección de datos...

tabla = tables[0].df

... como paso previo para manejarla mediante pandas, por ejemplo, accediendo las "celdas" [1-0] y [1-1]...

nombre = tabla.iloc[1,0]
dato = tabla.iloc[1,1]

... y mostrando su contenido

print(f'Nombre {nombre} -> Edad {dato}')
 
... para obtener por pantalla Nombre Juan -> Edad 23.

Esto que acabamos de hacer no parece gran cosa, pero detrás de ello tenemos toda la potencia del manejo de datos que permiten librerías como Pandas y todas aquellas que permiten el tratamiento de datos en Python. El que lo podamos conseguir partiendo de una tabla de datos de un documento pdf es gracias a Camelot. Conocer esta biblioteca es una buena forma de aprovechar el tiempo.

NOTAS

(1) Dado que el contenido de las tablas es frecuentemente numérico, he considerado preferible ubicar esta entrada (estas entradas, mejor) en la sección [Datos]. Aunque manejemos archivos de texto (pdf), si su contenido de interés son las tablas, éstas contienen datos, frecuentemente numéricos, además; así que Camelot  queda entendida aquí como una herramienta orientada a facilitar el acceso a datos. Creo que es un enfoque que se ajusta a la realidad.
(2) Podemos optar por hacerlo mediante ia, aunque tenemos algunas limitaciones que afectan a la confidencialidad (de trabajar con datos profesionales sensibles), de coste y/o de funcionalidad. Personalmente prefiero opciones que trabajen en local y que yo pueda llegar a entender; pero es una cuestión de preferencias.
(3) Al menos parcialmente, volviendo a él cuando necesites resolver algún problema. Otras web también ayudan a entender cómo crear script básicos pero de mucha utilidad [por ejemplo]. Te recomiendo especialmente [este vídeo], cuyo autor, además de conocimiento, muestra una gran capacidad didáctica.
(4) Por mantener la simplicidad del proyecto diremos que el pdf se encuentra en el mismo directorio que el script.
(5) Camelot permite guardar tablas en formato excel (to_excel()), csv (to_csv()), json (to_json()), html (to_html()), markdown (to_markdown()) y sqlite (to_sqlite())
(6) El uso más frecuente de Camelot es crear archivos (ver 5) con las tablas recuperadas, pero también es posible realizar diferentes manipulaciones con los datos mediante librerías como Pandas y todo lo que estas librerías permiten. De Pandas aun no hemos hablado en el blog, pero lo haremos en breve.