Estrarre dati dalle fatture con Python

Per estrarre i dati di una fattura da un PDF con Python, leggi il testo dal file, quindi estrai i campi nominati da quel testo. Due passaggi, forse quaranta righe di codice, e funziona magnificamente sulla prima fattura su cui lo provi. Poi il fornitore numero sette sposta il numero della sua fattura tre righe più in alto, e il tuo parser inizia a restituire None alle due del mattino.

Questa seconda parte è il vero argomento di questo articolo. La lettura è facile. Mantenere l'accuratezza nel tempo è il vero lavoro.

Punti chiave

  • Python estrae il testo della fattura in poche righe di codice. Mantenerlo corretto attraverso centinaia di layout dei fornitori è ciò che ti costa effettivamente.
  • Un PDF non è un formato di dati. È una descrizione tipografica di una pagina stampata, motivo per cui un'espressione regolare scritta sul layout di un fornitore è una cosa fragile.
  • Le espressioni regolari e i template per fornitore scalano linearmente con l'elenco dei fornitori. I modelli di visione non lo fanno, perché leggono la pagina anziché la stringa.
  • Qualunque cosa estragga i dati, il tuo codice deve controllare l'aritmetica. Le voci che non sommano al subtotale sono il rilevatore di bug più economico che scriverai mai.
  • L'estrazione è raramente ciò che fa smettere alle persone di sviluppare internamente. Lo sono la coda delle eccezioni, l'abbinamento dei fornitori e l'integrazione contabile.

Il formato PDF

Il formato PDF è versatile e consente la rappresentazione accurata di documenti cartacei, come le fatture, senza limitare il design. Nasce dal mondo della stampa cartacea ed è pensato per essere una rappresentazione digitale di una pagina stampata. Questa flessibilità offre grande libertà, permettendo ai creatori di PDF di esprimersi e di rispettare vari standard e regolamenti.

Tuttavia, il problema sorge quando i dati sono bloccati all’interno di un PDF. La natura libera e complessa del formato può entrare in conflitto con l'approccio strutturato e coerente necessario per gestire la grande mole di dati che un’azienda elabora ogni giorno.

Una schermata dei livelli del formato di file PDF
Livelli del formato di file PDF

Un PDF memorizza la posizione di ciascun glifo sulla pagina. Non memorizza il fatto che il numero in basso a destra sia il totale. Quella relazione vive nella tua testa, e ogni metodo di estrazione in questo articolo è un tentativo di codificarla.

Quali sono i passaggi per estrarre i dati da una fattura?

Una fattura è un documento che solitamente arriva in formato PDF. Una fattura formalizza una transazione tra un fornitore e un cliente, dove un prodotto o servizio viene scambiato per una somma precisa di denaro. Ecco i passaggi necessari per estrarre i dati da questo documento:

  1. Definire uno schema per i dati che vuoi estrarre dalle tue fatture
  2. Convertire la tua fattura da immagine a testo
  3. Estrarre il testo dalla tua fattura in base al tuo schema dati
  4. Raccogliere i dati estratti

Una schermata del processo di estrazione dei dati della fattura
Processo di estrazione dei dati della fattura

Definire uno schema per i dati della fattura

Le fatture arrivano da fornitori diversi e ognuno tende a personalizzare l’aspetto delle proprie fatture. Nonostante questa varietà, la sostanza di tutte le fatture è fondamentalmente la stessa: serve il fornitore, il cliente, un riferimento fattura, una data e un elenco di articoli con relativa quantità, descrizione e costo. Un ottimo modo per iniziare a definire il tuo formato è partire dal software di contabilità: probabilmente è proprio lì che andrai a registrare i dati estratti dalle fatture. Se vuoi solo un formato dati che copra ogni possibile caso, ti consiglio il sito schema.org che definisce una serie di formati dati standard per diversi ambiti, incluse le fatture. Parseur definisce uno schema dati predefinito per le tue fatture, ma puoi modificarlo in base alle tue esigenze rinominando i campi nella tua mailbox dedicata alle fatture, come spiegato qui. Una volta definito il tuo formato dati, puoi convertire la tua fattura da immagine a testo.

Ad esempio, puoi definire i seguenti campi per la tua fattura usando il formato JSON Swagger:

{
    "InvoiceNumber": {
        "type": "string",
        "description": "Il numero della fattura"
    },
    "InvoiceIssueDate": {
        "type": "string",
        "description": "La data della fattura"
    },
    "Items": {
        "type": "array",
        "description": "L'elenco degli articoli nella fattura",
        "items": {
            "type": "object",
            "properties": {
                "quantity": {
                    "type": "number",
                    "description": "La quantità dell'articolo"
                },
                "description": {
                    "type": "string",
                    "description": "La descrizione dell'articolo"
                },
                "unit_price": {
                    "type": "number",
                    "description": "Il prezzo unitario dell'articolo"
                },
                "price": {
                    "type": "number",
                    "description": "Il prezzo totale dell'articolo"
                }
            }
        }
    }
}

Scrivi tutto questo prima di scrivere qualsiasi codice di parsing. È il contratto che ogni metodo sottostante deve soddisfare, ed è ciò che in seguito fornirai a un modello di visione.

Convertire la tua fattura da immagine a testo

Una schermata di una fattura scattata da uno smartphone
Foto di una fattura scattata da uno smartphone

Un file PDF può contenere un’immagine. Ad esempio, un tuo dipendente può scattare una foto di una fattura con la fotocamera dello smartphone. Poi la salva come PDF e la invia all’ufficio contabilità. Il tuo team contabile dovrà estrarre i dati da questa fattura e inserirli in qualche modo nel sistema contabile senza errori. Il passaggio successivo è convertire questa immagine in testo utilizzando un sistema di riconoscimento ottico dei caratteri (OCR). Uno dei sistemi OCR più popolari è Tesseract. Tesseract è scritto in C e C++. Per usare Tesseract dal nostro programma Python, avremo bisogno di usare un binding come PyTesseract. Un binding è un modo per richiamare una libreria software (qui, Tesseract) da un linguaggio diverso da quello in cui è scritta (qui, Python). Esistono molti sistemi di questo tipo e i risultati variano notevolmente a seconda della tecnologia e della qualità della scansione del documento su cui lavorano. Parseur rileva in modo trasparente se il tuo documento è un’immagine e lo converte automaticamente in testo, internamente. Una volta che i dati del documento sono in formato testuale, sono pronti per essere estratti.

Estrarre il testo dalla tua fattura in base al tuo schema dati

Ora che il tuo PDF è in formato testo (o ricercabile), puoi usare la libreria Python pdftotext per estrarre i dati dal file PDF, come testo. Ecco un frammento di codice per estrarre il testo da un file PDF:

import pdftotext

# Carica la tua fattura
with open("invoice.pdf", "rb") as file_handle:
    pdf = pdftotext.PDF(file_handle)

# Itera su tutte le pagine
for page in pdf:
    print(page)

Dai a questo script il nome convert_pdf_to_text.py ed eseguilo: otterrai la fattura come testo nello standard output. Se vuoi reindirizzare l'output su un file, puoi eseguire:

$ python convert_pdf_to_text.py > invoice.txt

pdftotext ti fornisce una stringa piatta, che va bene per i campi di intestazione ma è inutile per le tabelle. Quando hai bisogno delle voci singole, rivolgiti invece a pdfplumber, perché mantiene le coordinate di ogni parola e può tentare di estrarre la tabella stessa:

import pdfplumber

with pdfplumber.open("invoice.pdf") as pdf:
    page = pdf.pages[0]

    # Parole con le loro posizioni sulla pagina
    for word in page.extract_words():
        print(word["text"], word["x0"], word["top"])

    # E un tentativo alla tabella delle voci
    table = page.extract_table()
    if table:
        for row in table:
            print(row)

Esegui questo codice su una fattura reale di un fornitore e molto spesso scoprirai che table è None. Questo non è un bug. È il primo segnale onesto che questo problema è più difficile di quanto sembri, e ci torneremo più avanti.

Ora che hai la fattura in formato testuale, puoi estrarre i dati che desideri da essa, utilizzando una combinazione delle seguenti tecniche:

  • Puoi usare un'espressione regolare per estrarre i dati desiderati. Le espressioni regolari sono un modo potente per estrarre dati da un testo, ma sono anche molto fragili. Se il formato della fattura cambia, dovrai aggiornare la tua espressione regolare. Inoltre, le espressioni regolari non si adattano bene all’estrazione di dati da tabelle.
  • Puoi utilizzare un sistema di templating visuale, sfruttando idealmente l'OCR Dinamico e l'OCR Zonale. Questo è un modo più avanzato per estrarre dati dal testo. È più robusto delle espressioni regolari, ma è anche più complesso da implementare.
  • Puoi passare la pagina a un modello di visione con uno schema e fargli leggere il documento come fa una persona. Questo è l'approccio che è cambiato negli ultimi due anni, e ad esso è dedicata un'apposita sezione qui sotto.

Estraiamo i dati dalla tua fattura usando il modulo delle espressioni regolari di Python re. Ecco un frammento di codice per estrarre il numero della fattura dalla tua fattura:

import re

# Carica la tua fattura
with open("invoice.txt", "r") as file_handle:
    invoice = file_handle.read()

# Estrai il numero della fattura
invoice_number = re.search(r"Invoice number: (\w+)", invoice).group(1)
print(invoice_number)

Chiama questo script extract.py ed eseguilo: otterrai il numero della fattura sullo standard output:

$ python extract.py

E otterrai qualcosa come:

INV-1234

Perché il tuo parser di fatture regex si rompe

Un'espressione regolare cerca una corrispondenza in una stringa. Una fattura è un'immagine. Tutto ciò che va storto deriva da questa discrepanza, e va storto in un piccolo numero di modi prevedibili:

  • L'etichetta si è spostata. Il tuo pattern è ancorato a Invoice number: e il nuovo template dice Invoice #, o mette il valore nella riga successiva invece che sulla stessa.
  • extract_table restituisce None. Gli estrattori di tabelle cercano righe di separazione. La maggior parte delle fatture dei fornitori allinea le colonne con gli spazi bianchi e non disegna alcun bordo.
  • Il testo esce nell'ordine sbagliato. I layout a due colonne e i blocchi di indirizzi fluttuanti si intrecciano quando la pagina viene appiattita in una stringa, quindi le tue righe con le voci arrivano mischiate.
  • La tabella si estende su più pagine. Le righe dalla due alla nove sono a pagina uno, dalla dieci alla quattordici a pagina due, con le intestazioni di colonna ripetute nel mezzo e una riga di subtotale che finge di essere un articolo.
  • Tre numeri sembrano tutti il totale. Subtotale, totale, importo dovuto e saldo precedente. Scegliere quello più grande è sbagliato in qualsiasi fattura che contenga un credito.
  • La scansione è una fotografia. L'OCR legge un 8 sbavato come un 3 e nulla a valle se ne accorge, perché 3 è una cifra perfettamente valida.
  • Celle unite e descrizioni su più righe. Una descrizione del prodotto va a capo su tre righe e la tua logica di divisione delle righe la trasforma in tre articoli senza prezzo.

Nessuno di questi è risolvibile con una migliore espressione regolare. Sono tutti problemi di layout travestiti da problemi di stringa. Questo è il punto in cui la maggior parte delle persone inizia a scrivere un template per fornitore, che cresce all'infinito, oppure cambia approccio.

L'approccio 2026: un modello di visione e uno schema

Il cambiamento utile è che non devi più appiattire la pagina in testo prima di poterne estrarre i dati. Un modello di visione guarda la fattura resa (rendered), quindi un fornitore che sposta il numero della propria fattura non è più un problema. Quello che fornisci non è un pattern, è lo schema che hai scritto all'inizio di questo articolo.

Vincola l'output in modo da ottenere le stesse chiavi ogni volta. Pydantic più una modalità di output strutturata, come gli OpenAI structured outputs, lo fa per te:

from typing import List
from pydantic import BaseModel

class LineItem(BaseModel):
    description: str
    quantity: float
    unit_price: float
    amount: float

class Invoice(BaseModel):
    vendor_name: str
    invoice_number: str
    invoice_date: str      # ISO 8601
    currency: str
    subtotal: float
    tax: float
    total: float
    line_items: List[LineItem]

# Renderizza la pagina del PDF in un'immagine, inviala a un modello di visione,
# e richiedi che la risposta corrisponda allo schema Invoice.
# Il modello riempie i campi. Non può inventarne la forma.

Questa è sinceramente la maggior parte del problema dell'estrazione risolto, ed è il motivo per cui questo approccio si è diffuso così velocemente. Introduce anche una nuova modalità di guasto che le regex non hanno mai avuto: una regex che non riesce a trovare il numero di fattura restituisce None, mentre un modello che non riesce a trovarlo a volte ne scriverà uno plausibile. La regola che ti tiene al sicuro è semplice. Il modello propone e il tuo codice verifica.

Se preferisci non eseguire il modello da solo, la stessa funzionalità è venduta come servizio gestito dai provider cloud, in Azure AI Document Intelligence e Amazon Textract AnalyzeExpense, che restituiscono entrambi campi di intestazione e voci in modo separato. Abbiamo descritto come l'approccio sottostante differisca dall'analisi basata su regole in Parser PDF basati su intelligenza artificiale o basati su regole e come si presenta applicato specificamente alle fatture in Elaborazione di fatture con Vision AI.

Il livello di convalida che devi scrivere tu stesso

Qualunque cosa abbia prodotto il tuo JSON, questi controlli appartengono al tuo codice, non al punteggio di affidabilità dell'estrattore. Sono economici, sono deterministici e rilevano gli errori che costano denaro:

  1. subtotale + tasse + spedizione - sconto corrisponde a totale, con la precisione di un centesimo.
  2. Gli importi delle voci si sommano al subtotale. In caso contrario, hai saltato una riga o ne hai inventata una.
  3. Ogni quantità * prezzo_unitario è uguale al suo rispettivo importo.
  4. La data viene analizzata correttamente e non è nel futuro.
  5. Il numero di fattura non è già stato pagato per quel fornitore. I pagamenti duplicati sono il bug più costoso nella contabilità fornitori.
  6. Il nome del fornitore si risolve in un record nella tua anagrafica fornitori.
  7. Le coordinate bancarie del beneficiario corrispondono a quelle già in archivio per quel fornitore. Un cambiamento qui è un controllo anti-frode, non un controllo dei dati.
  8. La valuta è una di quelle con cui operi effettivamente.
  9. Il numero dell'ordine di acquisto esiste e le relative quantità e i prezzi corrispondono se esegui una corrispondenza a due o a tre vie.
  10. Ogni campo obbligatorario è presente e non vuoto.

Tutto ciò che fallisce questi controlli va a una persona, non nei registri contabili:

def validate(invoice):
    errors = []

    if abs(invoice.subtotal + invoice.tax - invoice.total) > 0.01:
        errors.append("totals_do_not_add_up")

    line_sum = sum(item.amount for item in invoice.line_items)
    if invoice.line_items and abs(line_sum - invoice.subtotal) > 0.01:
        errors.append("line_items_do_not_sum_to_subtotal")

    if not invoice.invoice_number:
        errors.append("missing_invoice_number")

    return errors

Dieci righe di aritmetica rileveranno più problemi reali di qualsiasi quantità di tuning dei prompt.

E per quanto riguarda invoice2data e le altre librerie?

invoice2data merita una menzione onesta, perché è il primo risultato su cui finiscono molte persone ed è un software genuinamente buono. È uno strumento a riga di comando e una libreria Python che confronta le fatture con i template YAML che scrivi per ogni fornitore, con le regole di corrispondenza nel controllo di versione piuttosto che sepolte nel tuo codice. Se hai una decina di fornitori che non cambiano mai il loro layout, ti servirà bene per anni.

Il limite è nella progettazione, non nella qualità. Un template per fornitore significa che la tua manutenzione cresce con il tuo elenco di fornitori, e i template si rompono esattamente per i motivi sopra elencati. Tra venti e trenta layout attivi, la persona che si occupa della manutenzione dei template sta facendo più lavoro della persona che in passato riscriveva a mano le fatture.

Lo stesso ragionamento vale per il più ampio scaffale delle librerie. pdfplumber, PyMuPDF, pdftotext e pytesseract sono tutti eccellenti nel loro vero lavoro, ovvero estrarre caratteri e coordinate da una pagina. Nessuno di loro è mai stato progettato per sapere quale numero è il totale. Confrontiamo il set più ampio nella nostra rassegna dei migliori parser PDF e delle migliori API di estrazione dati.

Raccogliere i dati estratti

Con Python, puoi iterare sui file delle fatture in una determinata cartella ed estrarre i dati da essi. Mettiamo di voler estrarre il numero della fattura e l’importo totale, e salvare il risultato in formato CSV:

import os
import re

import pdftotext

# Itera su tutti i file PDF nella cartella
for filename in os.listdir("invoices/"):
    if not filename.endswith(".pdf"):
        continue

    # Carica la tua fattura
    with open("invoices/" + filename, "rb") as file_handle:
        pdf = pdftotext.PDF(file_handle)

    # Stampa l'intestazione della colonna CSV
    print("InvoiceNumber,TotalAmount")

    # Itera su tutte le pagine
    for page in pdf:
        # Estrai i dati
        invoice_number = re.search(r"Invoice number: (\w+)", page).group(1)
        total_amount = re.search(r"Total amount: (\w+)", page).group(1)
        print(invoice_number, total_amount, sep=",")

Chiama questo script extract_to_csv.py ed eseguilo: otterrai il numero della fattura e l'importo totale sullo standard output, che puoi reindirizzare a un file CSV da aprire in seguito con il tuo software di fogli di calcolo preferito, come Excel:

$ python extract_to_csv.py > invoices.csv

Una cartella di file CSV è il punto in cui la maggior parte degli script per le fatture si ferma, ed è anche dove inizia la contabilità onesta. Qualcuno deve ancora importarli, abbinare i fornitori, inseguire le righe che il sistema contabile ha respinto e capire cosa fare con la fattura che non ha superato la convalida alle 2 di notte. Questo lavoro non appare nel tuo script e non appare nella tua fattura dei token.

Quando smettere di sviluppare

Ecco la parte che la maggior parte dei vendor salta, quindi lo diremo per primi. Se hai una manciata di fornitori fissi, un ingegnere in grado di monitorare una pipeline e nessuno in attesa dei dati, scrivi lo script. Un modello di visione più uno schema più le dieci righe di convalida di cui sopra ti porteranno molto lontano con pochissimi soldi e ne capirai ogni parte.

Il conto per lo sviluppo arriva più tardi, e mai nell'estrazione. Arriva nelle parti che nessuno prototipa:

  • La coda delle eccezioni. Il tuo team contabile ha bisogno di una schermata in cui facendo clic su un campo questo venga evidenziato sulla fattura, in modo da poterlo correggere in quattro secondi invece di quaranta. Questo è un prodotto, non uno script.
  • Abbinamento dei fornitori. "ACME Ltd", "Acme Limited" e "ACME LTD." sono un solo fornitore e il registro contabile non ne accetterà tre.
  • Rilevamento dei duplicati. La stessa fattura arriva come allegato e-mail il martedì e come estratto conto PDF il venerdì.
  • La macchina a stati. Code, tentativi, guasti parziali e sapere quale delle 300 fatture di ieri notte è effettivamente passata.
  • L'audit trail. Cosa è stato estratto, cosa è stato modificato da un essere umano, chi lo ha approvato e quando. Il dipartimento finanziario lo chiederà, di solito durante un audit.
  • Tutto ciò che viene dopo il JSON. Mappatura dei campi nel sistema contabile, codifica GL, abbinamento degli ordini di acquisto e le righe che rifiuta.

I segnali chiari che è giunto il momento di acquistare anziché costruire sono questi. Hai superato circa venti o trenta layout di fornitori attivi. Hai bisogno delle voci di riga, non solo dei campi di intestazione. Più di una manciata delle tue fatture arriva come scansione. Il tuo team contabile, non il tuo team di ingegneri, deve correggere gli errori. Le estrazioni fallite stanno ritardando i pagamenti. Oppure, più comunemente, la persona che mantiene il parser ha smesso di sviluppare e rilasciare qualsiasi altra cosa.

Come lo gestisce Parseur

Parseur è un document parser che esegue l'intero ciclo, non solo la fase di estrazione. Le fatture arrivano a un indirizzo di posta elettronica dedicato, tramite l'API o da una cartella monitorata. Il motore di Vision AI legge PDF, scansioni e fotografie, e il motore Text AI legge e-mail e documenti di testo. I campi escono nominati e tipizzati, e le voci escono come righe. Non ci sono template da scrivere e niente da mantenere quando un fornitore ridisegna la propria fattura.

Quello che ottieni oltre al JSON è la metà su cui questo articolo ti ha messo in guardia. I dati estratti sono revisionabili e correggibili sul posto, quindi un addetto alla contabilità corregge un totale letto male senza aprire un ticket. Le correzioni alimentano di nuovo l'estrazione. E i dati vanno dove devono andare tramite integrazione webhook diretta, Make, Zapier o Microsoft Power Automate, o direttamente dall'API come JSON.

Se vuoi vedere il set di campi che estraiamo di default dalle fatture, è documentato sulla nostra pagina OCR delle fatture e il flusso di lavoro più ampio è coperto nell'acquisizione dei dati delle fatture.

Crea il tuo account gratuito
Risparmia tempo e fatica con Parseur. Automatizza i tuoi documenti.

Conclusione

Estrarre i dati di una fattura da un PDF con Python è un problema risolto per circa cento fatture e uno irrisolto per diecimila. Non è il codice che cambia tra questi due numeri. Ciò che cambia è quanti layout di fornitori stai silenziosamente accettando di mantenere e chi viene chiamato quando uno di loro si sposta.

Scrivi lo script. Vale sinceramente la pena farlo una volta, se non altro per scoprire esattamente quale delle sette modalità di guasto di cui sopra ti colpisce per prima. Quindi decidi onestamente se i prossimi sei mesi del tuo tempo verranno spesi meglio per l'ottava. Se la risposta è no, Parseur lo fa dal 2016 e ti toglierà il problema dalle mani.

Ultimo aggiornamento il

Inizia subito

Pronto ad automatizzare
l’estrazione dati dai tuoi documenti?

Inizia gratis in pochi minuti e scopri come Parseur si integra nel tuo flusso di lavoro.

Nessun modello da addestrare
Automatizza l’inserimento dati da qualsiasi documento
Dalla web app all'API, scala con te

Domande Frequenti

Le domande che gli sviluppatori si pongono effettivamente una volta che il primo script per le fatture è in funzione e il secondo fornitore lo ha mandato in tilt.

Leggi il testo dal PDF con una libreria come pdfplumber o pdftotext, quindi estrai i campi nominati da quel testo. Per i PDF nati in formato digitale, è un lavoro in due passaggi. Per le scansioni, è necessaria prima una passata con l'OCR per trasformare l'immagine in testo. La parte che decide se funziona in produzione non è la lettura, ma come si passa da un muro di testo al numero di fattura, alla data, al fornitore e alle voci quando ogni fornitore li dispone in modo diverso.

invoice2data è uno strumento a riga di comando e una libreria Python open source che estrae i campi dalle fatture utilizzando template YAML che scrivi per ciascun fornitore. È una buona soluzione quando hai un gruppo piccolo e stabile di fornitori e desideri che la logica di corrispondenza sia sotto controllo di versione anziché nel tuo codice. Smette di essere una buona scelta nel momento in cui scrivere e mantenere un template per fornitore costa più della digitazione manuale che ha sostituito.

Tratta la tabella delle voci come un'estrazione separata dai campi di intestazione e ricostruiscila su più pagine prima di analizzarla. L'extract_table di pdfplumber funziona su tabelle pulite con righe e non restituisce nulla su quelle senza bordi, ovvero la maggior parte delle fatture dei fornitori. Il pattern affidabile è rilevare i limiti delle colonne una volta per ogni layout del fornitore, portarli oltre le interruzioni di pagina, eliminare le righe di intestazione ripetute e quindi verificare che le righe estratte sommate diano il subtotale. In caso contrario, hai saltato una riga.

Con controlli deterministici nel tuo codice, mai con la sola affidabilità dell'estrattore. Il set principale riguarda l'aritmetica e l'identità. Conferma che il subtotale più tasse più spedizione meno sconto corrisponda al totale, che le voci sommino al subtotale, che la data sia formattata correttamente e non sia nel futuro, che il numero di fattura non sia già stato pagato per quel fornitore, che il fornitore esista nella tua anagrafica e che la valuta sia quella prevista. Qualsiasi elemento che fallisce questi controlli va a un essere umano invece che nei registri contabili.

Quando l'estrazione non è più la parte difficile. Chiamare un modello di visione è economico e veloce da prototipare, quindi se hai una manciata di fornitori fissi e qualcuno che può monitorare la pipeline, costruiscilo. Il conto arriva più tardi, nella logica di coda e riprova, nella schermata di revisione delle eccezioni di cui il tuo team contabile ha bisogno, nel rilevamento dei duplicati, nella corrispondenza dei fornitori, nell'audit trail e nell'integrazione contabile. Contali prima di confrontare i prezzi per pagina.

Sì, ma una scansione ha bisogno di una passata OCR prima che una qualsiasi delle librerie di testo possa vedere qualcosa. Una fattura fotografata o scansionata è un'immagine avvolta in un PDF, quindi pdfplumber e pdftotext restituiscono una stringa vuota su di essa. Il percorso open-source abituale è Tesseract tramite il binding pytesseract, dopo aver raddrizzato e pulito l'immagine. I moderni modelli di visione saltano completamente quel passaggio e leggono l'immagine direttamente.

Non esiste una libreria per le fatture, ma solo librerie PDF più la tua logica. pdfplumber è solitamente la prima scelta perché espone le parole con le loro coordinate e ha un estrattore di tabelle. PyMuPDF è più veloce su grandi lotti. pdftotext è la soluzione più piccola che funziona quando hai solo bisogno del testo non elaborato. pytesseract gestisce le scansioni. Ognuno di essi ti fornisce testo o riquadri. Nessuno di loro ti dice quale numero è il totale.

Perché un'espressione regolare cerca una corrispondenza in una stringa e una fattura è un'immagine. Il tuo pattern è ancorato a un'etichetta, a un'interruzione di riga o alla posizione di una colonna che il nuovo template del fornitore ha spostato. Le fatture sono documenti visivi semi-strutturati, quindi ciò che causa problemi sono i layout, non le stringhe. Tabelle divise su più pagine, intestazioni ripetute, celle unite e la differenza tra subtotale, totale e importo dovuto non sono risolvibili con una migliore espressione regolare.

Sì, ed è ora il percorso più breve da un PDF a JSON strutturato, ma solo con uno schema e un validatore attorno. Un modello di visione legge la fattura come fa un essere umano, quindi se un fornitore cambia layout non è più un problema. Vincola l'output con uno schema JSON, usando strumenti come gli OpenAI structured outputs o un modello Pydantic, in modo da ottenere le stesse chiavi ogni volta. Poi controlla tu stesso l'aritmetica. Un modello che non riesce a trovare il numero di fattura a volte ne produrrà uno plausibile.

L'accuratezza dipende dal campo e dalla scansione, non dal prodotto, quindi tratta qualsiasi percentuale da prima pagina come puro marketing. I totali stampati e i numeri di fattura su un PDF nativo digitale pulito vengono restituiti quasi perfettamente. È proprio sugli stessi campi in una scansione fotografata, storta e a basso contrasto che le cifre vengono confuse e dove un carattere sbagliato costa denaro reale. Il numero che vale la pena misurare non è l'accuratezza dei caratteri, ma quante fatture arrivano al tuo sistema contabile senza che un essere umano le tocchi.

Smetti di scrivere cose specifiche per ogni fornitore. Qualsiasi approccio che necessiti di un template, un set di espressioni regolari o una mappa di coordinate per ogni fornitore cresce linearmente con il tuo elenco di fornitori e non riduce il carico di lavoro di nessuno dopo circa venti o trenta layout attivi. Un modello che legge il documento visivamente è indipendente dal formato per progettazione, motivo per cui i cambiamenti di layout smettono di essere un evento di manutenzione. Ciò che richiede ancora la tua attenzione è la coda delle eccezioni, e questo è un problema di flusso di lavoro piuttosto che di estrazione.

Scrivere un CSV richiede poche righe di Python ed è la metà facile del lavoro. La metà difficile è inserire i dati nel sistema che paga il conto, il che significa mappare i nomi dei tuoi campi nel suo schema, abbinare i fornitori ai record esistenti, gestire le righe che rifiuta e riprovare le chiamate che falliscono. Pianifica quella metà fin dall'inizio, perché una cartella di file CSV che qualcuno deve ancora importare a mano non ha fatto risparmiare un pomeriggio a nessuno.