Curso de Automatización (RPA)

Clase 3: Extrayendo Totales de Facturas PDF a Excel

⏱️ Tiempo de lectura: 15 minutos
🧩 Actividades: 1
📚 Nivel: Intermedio

📄 Un Desafío del Mundo Real: Facturas en PDF

Llegamos a una de las tareas de automatización más solicitadas: extraer información de archivos PDF. Muchas empresas reciben facturas, reportes o resúmenes en este formato. Copiar y pegar manualmente los datos importantes (como fechas, números de factura o totales) a una hoja de Excel es tedioso y propenso a errores.

Hoy construiremos un robot que se encargará de esta tarea. Leerá una carpeta llena de facturas en PDF, identificará el monto total en cada una y creará un reporte en Excel con el nombre del archivo y el total extraído.

📚 Librerías para la Misión

Para esta tarea necesitaremos un conjunto de herramientas más especializado. Abre tu terminal (con tu entorno virtual activado) e instala las siguientes librerías:

Terminal
pip install pandas openpyxl PyMuPDF
  • pandas y openpyxl: Nuestros viejos conocidos. Pandas nos ayudará a estructurar los datos extraídos y a guardarlos cómodamente en un archivo Excel.
  • PyMuPDF: Una librería muy rápida y eficiente para abrir archivos PDF y extraer su contenido de texto. La instalamos con `PyMuPDF` pero la importamos en Python como `fitz`.
¿Qué son las Expresiones Regulares (Regex)?

Para encontrar el "Total" en el texto desordenado de un PDF, usaremos una técnica poderosa llamada expresiones regulares. Son patrones de búsqueda que nos permiten encontrar texto que sigue una estructura específica, como "la palabra TOTAL seguida de un número con decimales". No te preocupes si parece complejo, ¡verás qué útil es!

📄 El Código del Extractor

Crea un archivo extractor_pdf.py. Antes de ejecutarlo, asegúrate de crear una carpeta llamada facturas en el mismo directorio y colocar dentro algunos archivos PDF de facturas que tengas a mano para probar.

extractor_pdf.py

import os
import re
import fitz  # La librería PyMuPDF se importa como fitz
import pandas as pd

# --- CONFIGURACIÓN ---
CARPETA_FACTURAS = "facturas"
ARCHIVO_EXCEL_SALIDA = "reporte_de_totales.xlsx"

def extraer_total_de_texto(texto_completo: str) -> float:
    """
    Usa expresiones regulares para encontrar el primer monto total en el texto.
    """
    # Patrón que busca 'Total', 'TOTAL', etc., seguido de un número.
    # Soporta formatos como: $1.234,56 o 1234.56
    patron = re.compile(r"Total.*?([\d.,]+)", re.IGNORECASE)
    
    coincidencias = patron.findall(texto_completo)
    
    if not coincidencias:
        return 0.0

    # Procesamos la primera coincidencia encontrada
    monto_str = coincidencias[0]
    
    # Limpiamos el string para convertirlo a número
    monto_limpio = monto_str.replace(".", "").replace(",", ".")
    
    try:
        return float(monto_limpio)
    except ValueError:
        return 0.0

def procesar_pdfs_en_carpeta(ruta_carpeta: str) -> pd.DataFrame:
    """
    Recorre una carpeta, procesa cada PDF y devuelve un DataFrame con los resultados.
    """
    datos_para_excel = []

    if not os.path.exists(ruta_carpeta):
        print(f"❌ Error: La carpeta '{ruta_carpeta}' no fue encontrada.")
        return pd.DataFrame()

    print(f"📂 Analizando archivos en la carpeta: {ruta_carpeta}")
    
    for nombre_archivo in os.listdir(ruta_carpeta):
        if nombre_archivo.lower().endswith(".pdf"):
            ruta_completa = os.path.join(ruta_carpeta, nombre_archivo)
            
            try:
                # Abrir el PDF con fitz
                doc = fitz.open(ruta_completa)
                texto_total = ""
                # Extraer texto de todas las páginas
                for pagina in doc:
                    texto_total += pagina.get_text()
                
                doc.close()
                
                # Extraer el monto total del texto
                total = extraer_total_de_texto(texto_total)
                
                datos_para_excel.append({
                    "Nombre de Archivo": nombre_archivo,
                    "Total Extraído": total
                })
                print(f"  ✔ Procesado '{nombre_archivo}': Total encontrado = {total:.2f}")

            except Exception as e:
                print(f"  ⚠️ Error al procesar el archivo '{nombre_archivo}': {e}")

    return pd.DataFrame(datos_para_excel)

# --- Punto de Entrada Principal ---
if __name__ == "__main__":
    print("🤖 Iniciando robot extractor de totales de facturas PDF...")
    
    df_resultados = procesar_pdfs_en_carpeta(CARPETA_FACTURAS)
    
    if not df_resultados.empty:
        # Guardar los resultados en un archivo Excel
        df_resultados.to_excel(ARCHIVO_EXCEL_SALIDA, index=False)
        print(f"\n✅ ¡Proceso finalizado! Se ha creado el archivo '{ARCHIVO_EXCEL_SALIDA}'.")
    else:
        print("\nℹ️ No se procesaron archivos o no se encontraron datos.")
                    

🧐 Desglose del Código

  • extraer_total_de_texto(): Esta es la función clave. Recibe el texto de un PDF y utiliza re.findall() para buscar un patrón. El patrón Total.*?([\d.,]+) busca la palabra "Total" (sin importar mayúsculas/minúsculas), seguida de cualquier carácter (.*?), hasta encontrar un grupo de números que pueden incluir comas y puntos.
  • Limpieza de datos: Una vez que encuentra un posible monto como "1.234,56", el código lo limpia (quita el punto de miles, cambia la coma decimal por un punto) para poder convertirlo a un número (float) que Python pueda entender.
  • procesar_pdfs_en_carpeta(): Esta función orquesta el proceso. Usa os.listdir() para obtener todos los archivos de la carpeta de facturas.
  • fitz.open(ruta): Abre un archivo PDF. Luego, recorremos cada página (`for pagina in doc:`) y extraemos su texto con pagina.get_text().
  • pd.DataFrame() y .to_excel(): Al final, usamos el poder de pandas para tomar nuestra lista de resultados y convertirla en una tabla que se guarda fácilmente en un archivo de Excel.
¡Tu Turno! Crea la carpeta facturas, poné algunos PDFs adentro y ejecuta el script con python extractor_pdf.py. ¡Observa cómo se crea tu reporte en Excel!