7 min

Automatizar recibos fiscales con Gmail API y Docling

Cómo descargar y procesar cientos de facturas de Gmail automáticamente con Python, la Gmail API y Docling para la declaración de impuestos: de 7 horas a 7 minutos.

Imagen destacada: Docling analizando más de 200 PDF y convirtiéndolos a markdown sencillo

¿Cómo lleva nadie el control de los gastos empresariales para la autoliquidación en Reino Unido?

Para mí, esto empezó porque llevo varios proyectos: SimRacingCockpit, este sitio (Converly) y diversos trabajos de consultoría. El último año fiscal pasé horas haciendo clics manuales por Gmail, descargando 307 PDF uno a uno. Facturas de Stripe de Semrush y Ahrefs. Recibos digitales de consultoría de proveedores. Facturas escaneadas de equipo de Amazon. Cada uno necesitaba descarga, listo para analizar. (Sí, podría contratar un contable).

Este año, en lugar de limitarme a contratar un contable, construí un script de Python que lo hace en minutos.

Github: https://github.com/richyBaxter/automate-tax-receipts

Encontrar Docling

Tras perder un día con PyPDF2, investigué soluciones reales de OCR. El panorama es:

  • Tesseract OCR: gratuito, de código abierto, 85-95% de precisión con un preprocesamiento de imagen adecuado
  • Google Cloud Vision: 1,50 $ por cada 1.000 páginas tras la capa gratuita, 98,7% de precisión en facturas limpias
  • AWS Textract: precios variables según la API utilizada (AnalyzeExpense para facturas), contacta con AWS para tarifas concretas
  • IBM Docling: gratuito, de código abierto, entiende la estructura del documento

Me decidí por Docling. Es gratuito (importante para una tarea anual), usa modelos de OCR reales en lugar de una simple extracción de texto y entiende la estructura del documento (cabeceras, tablas, líneas de detalle). Solo la instalación tenía algunas dependencias: necesita onnxruntime para los modelos de ML:

pip install docling onnxruntime

Realidad del hardware: en mi RTX 3090, procesar 307 PDF llevó unos 4 minutos. Solo con CPU fue más lento (horas), pero igual de fiable. Nada terrible, aunque la aceleración por GPU funciona muy bien.

Docling: Repo - https://github.com/docling-project/docling

La solución con la Gmail API

La API de Gmail es algo engorrosa de configurar. Google Console (a menos que vivas y respires Google Console) se siente como una aplicación que tienes que aprender desde cero cada vez que te acercas a ella. Gracias a Dios por Gemini.

En resumen: el flujo OAuth de Google requiere crear un proyecto en Cloud Console, habilitar la Gmail API, descargar las credenciales y luego completar una autorización basada en navegador que genera un token. La primera vez me llevó unos cuantos clics de más, pero estoy razonablemente seguro de que la próxima vez podría hacerlo con menos ayuda.

Una vez autenticado, el bucle de descarga de facturas es directo:

from googleapiclient.discovery import build

service = build('gmail', 'v1', credentials=creds)
results = service.users().messages().list(
    userId='me',
    q='has:attachment after:2024/04/05 before:2025/04/06'
).execute()

for msg in results.get('messages', []):
    # Get full message with attachments
    message = service.users().messages().get(
        userId='me', 
        id=msg['id']
    ).execute()
    
    # Download attachments
    for part in message['payload'].get('parts', []):
        if part['filename']:
            attachment = service.users().messages().attachments().get(
                userId='me',
                messageId=msg['id'],
                id=part['body']['attachmentId']
            ).execute()
            
            # Save with YYYY-MM-DD prefix for sorting
            date = extract_date_from_email(message)
            filename = f"{date}_{part['filename']}"
            save_attachment(attachment, filename)

El patrón del nombre de archivo es importante. Antepongo a todo YYYY-MM-DD_ para que se ordenen cronológicamente en la carpeta. Cuando mi contable necesita "todos los recibos de abril", puedo simplemente ordenar por nombre de archivo en lugar de hurgar en los metadatos.

El límite de tasa es real, pero razonable. Gmail permite 250 unidades de cuota por segundo para lectura de mensajes, y cada descarga de adjunto cuesta 5 unidades. Para 307 adjuntos, me mantuve muy por debajo del límite.

Integración con Docling

Tras la descarga, cada PDF pasa por el OCR de Docling. La lógica de extracción de importes usa varios patrones regex porque los formatos de factura son bastante inconsistentes (salvo la parte del dinero, obviamente).

from docling.document_converter import DocumentConverter

converter = DocumentConverter()
result = converter.convert("invoice.pdf")
markdown_text = result.document.export_to_markdown()

# Amount extraction patterns (confidence levels)
patterns = {
    'high': [
        r'Total[:\s]+£?([\d,]+\.\d{2})',
        r'Amount Due[:\s]+£?([\d,]+\.\d{2})',
    ],
    'low': [
        r'£([\d,]+\.\d{2})',  # Any £ amount
        r'(\d+\.\d{2})\s*GBP',  # Any decimal with GBP
    ]
}

Tasa de éxito en 307 facturas: 89% (274 extraídas correctamente). El 11% que falló fue mayoritariamente:

  • Facturas con divisas mezcladas (importes en USD junto a GBP)
  • Escaneos de calidad muy pobre con ruido
  • Importes manuscritos en recibos escaneados (Docling es bueno, pero no magia)

Para las que fallaron, las añadí a una lista de revisión manual. Aun así, más rápido que hacer clic en 307 adjuntos a mano.

Para las que sí funcionaron, pasamos de algún PDF a esto:

Factura en PDF procesada por Docling: ¡muy buena!

Poniéndolo todo junto

Bien, acabé con dos scripts de Python separados en lugar de nada sofisticado.

El script uno gestiona la descarga de Gmail (download_gmail_attachments.py). Se autentica mediante el flujo OAuth de Google —genuinamente molesto la primera vez— y luego busca cualquier correo con un adjunto dentro del rango de fechas del año fiscal. Descarga todo con el prefijo de nombre de archivo YYYY-MM-DD para poder ordenar cronológicamente después. Tarda unos 2 minutos para 307 recibos.

El script dos procesa el OCR (process_receipts_ocr.py). Recorre todos los PDF, ejecuta Docling en cada uno, usa patrones regex para extraer importes y luego genera un resumen en CSV para mi contable. El 11% que falla se marca para revisión manual —sobre todo facturas con divisas mezcladas o escaneos realmente terribles—. Son 4 minutos en mi RTX 3090, más otros 30 segundos para generar el CSV.

Tiempo total: 7 minutos. Comparado con las tres tardes que pasé el año pasado haciendo clics por Gmail (unas 7 horas), mereció absolutamente la pena construirlo.

Lo bueno de mantenerlos separados es que el descargador de Gmail funciona por sí solo si solo necesitas los adjuntos sin OCR. De hecho, lo he usado en otros proyectos donde solo necesitaba descargar archivos en lote de remitentes concretos.

Un buen truco de productividad con IA

El ahorro de tiempo es agradable (de 7 horas a 7 minutos), pero lo que creo que hace que valga la pena es la repetibilidad. El próximo año fiscal puedo ejecutar el mismo script con fechas actualizadas. Al siguiente, lo mismo. Si mi contable cambia lo que necesita, ajusto el formato de salida del CSV una vez y listo. ¡Gracias a Claude!

He subido ambos scripts a GitHub con instrucciones de configuración. La parte de Gmail es OAuth estándar + llamadas a la API. La integración con Docling llevó más trabajo para dejar los patrones regex bien, pero cubren la mayoría de formatos de factura que he encontrado.

Si gestionas volúmenes similares de recibos empresariales para la autoliquidación en Reino Unido (o tu declaración de impuestos en EE. UU.), siéntete libre de usar uno o ambos. Genuinamente me interesaría saber qué enfoque estás siguiendo: ¿sigues haciendo clics por Gmail uno a uno o has encontrado algo que funcione mejor?

Artículos relacionados