Rechnungsdaten aus PDF mit Python extrahieren

Um Rechnungsdaten aus einem PDF mit Python zu extrahieren, lesen Sie den Text aus der Datei aus und ziehen dann benannte Felder aus diesem Text. Zwei Schritte, vielleicht vierzig Zeilen Code, und es funktioniert wunderbar bei der ersten Rechnung, bei der Sie es versuchen. Dann verschiebt Lieferant Nummer sieben seine Rechnungsnummer um drei Zeilen nach oben, und Ihr Parser fängt an, um zwei Uhr morgens None zurückzugeben.

Dieser zweite Teil ist das eigentliche Thema dieses Artikels. Das Auslesen ist einfach. Das Korrekt-Bleiben ist die eigentliche Arbeit.

Wichtigste Erkenntnisse

  • Python extrahiert Rechnungstexte in wenigen Zeilen. Es über hunderte von Lieferantenlayouts hinweg korrekt zu halten, ist das, was Sie tatsächlich kostet.
  • Ein PDF ist kein Datenformat. Es ist eine typografische Darstellung einer gedruckten Seite, weshalb ein Regex, der für das Layout eines Lieferanten geschrieben wurde, eine fehleranfällige Sache ist.
  • Reguläre Ausdrücke und pro-Lieferant-Vorlagen skalieren linear mit Ihrer Lieferantenliste. Vision-Modelle tun das nicht, weil sie die Seite lesen statt der Zeichenfolge.
  • Was auch immer die Daten extrahiert, Ihr eigener Code muss die Arithmetik überprüfen. Einzelposten, die nicht zur Zwischensumme passen, sind der günstigste Fehlerdetektor, den Sie jemals schreiben werden.
  • Die Extraktion ist selten das, was Leute vom Bauen abhält. Die Ausnahme-Warteschlange, der Lieferantenabgleich und die Buchhaltungsintegration sind es.

Das PDF-Format

Das PDF-Format ist vielseitig und ermöglicht die genaue Darstellung von Papierdokumenten wie Rechnungen, ohne deren Gestaltung einzuschränken. Es stammt aus der Welt des Papierdrucks und ist als digitale Darstellung einer Druckseite konzipiert. Diese Flexibilität bietet große Freiheit, sodass PDF-Ersteller sich ausdrücken und verschiedene Normen und Vorschriften einhalten können.

Die Herausforderung besteht jedoch darin, dass die Daten in einem PDF-Dokument eingeschlossen sind. Die freie Form und Komplexität des Formats kann im Widerspruch zu dem strukturierten und konsistenten Ansatz stehen, der für die Verwaltung der riesigen Datenmengen erforderlich ist, die ein Unternehmen täglich verarbeitet.

Eine Bildschirmaufnahme der Ebenen des PDF-Dateiformats
Ebenen des PDF-Dateiformats

Ein PDF speichert, wo jedes Zeichen auf der Seite sitzt. Es speichert nicht die Tatsache, dass die Zahl unten rechts die Gesamtsumme ist. Diese Beziehung existiert nur in Ihrem Kopf, und jede Extraktionsmethode in diesem Artikel ist der Versuch, diese Beziehung zu kodieren.

Was sind die Schritte, um Daten aus einer Rechnung zu extrahieren?

Eine Rechnung ist ein Dokument, das in der Regel im PDF-Format vorliegt. Eine Rechnung formalisiert eine Transaktion zwischen einem Lieferanten und einem Kunden, bei der ein Produkt oder eine Dienstleistung gegen einen bestimmten Geldbetrag ausgetauscht wird. Hier sind die Schritte, die erforderlich sind, um Daten aus diesem Dokument zu extrahieren:

  1. Definieren Sie ein Schema für die Daten, die Sie aus Ihren Rechnungen extrahieren möchten
  2. Konvertieren Sie Ihre Rechnung von einem Bild in Text
  3. Extrahieren Sie den Text aus Ihrer Rechnung gemäß Ihrem Datenschema
  4. Sammeln Sie die extrahierten Daten

Eine Bildschirmaufnahme des Prozesses der Rechnungdatenextraktion
Prozess der Rechnungdatenextraktion

Definieren Sie ein Schema für Ihre Rechnungsdaten

Rechnungen stammen von verschiedenen Lieferanten, und jeder Lieferant neigt dazu, das Aussehen seiner Rechnungen individuell zu gestalten. Trotz dieser realen Vielfalt in der Form ist der Inhalt aller Rechnungen im Grunde derselbe: Man braucht einen Lieferanten, einen Kunden, eine Rechnungsreferenz, ein Datum und eine Liste von Posten mit zugehöriger Menge, Beschreibung und Kosten. Ein guter Ausgangspunkt für die Definition Ihres Rechnungsformats wäre Ihre Buchhaltungssoftware, da Sie Ihre extrahierten Rechnungsdaten höchstwahrscheinlich dort speichern werden, richtig? Wenn Sie nur ein Datenformat wünschen, das alle Fälle abdeckt, empfehle ich Ihnen die Website schema.org, die praktischerweise eine Reihe von Industriestandard-Datenformaten für viele Dinge definiert, einschließlich Rechnungen. Parseur definiert ein Standarddatenschema für Ihre Rechnungen, aber Sie können es an Ihren Anwendungsfall anpassen, indem Sie die Felder in Ihrem Rechnungseingang umbenennen, wie hier erläutert. Sobald Ihr Datenformat definiert ist, können Sie Ihre Rechnung von einem Bild in Text konvertieren.

Sie können beispielsweise die folgenden Felder für Ihre Rechnung im JSON-Swagger-Format definieren:

{
    "InvoiceNumber": {
        "type": "string",
        "description": "The invoice number"
    },
    "InvoiceIssueDate": {
        "type": "string",
        "description": "The invoice date"
    },
    "Items": {
        "type": "array",
        "description": "The list of items in the invoice",
        "items": {
            "type": "object",
            "properties": {
                "quantity": {
                    "type": "number",
                    "description": "The quantity of the item"
                },
                "description": {
                    "type": "string",
                    "description": "The description of the item"
                },
                "unit_price": {
                    "type": "number",
                    "description": "The unit price of the item"
                },
                "price": {
                    "type": "number",
                    "description": "The total price of the item"
                }
            }
        }
    }
}

Schreiben Sie dies auf, bevor Sie irgendeinen Parsing-Code verfassen. Es ist der Vertrag, den jede der unten genannten Methoden erfüllen muss, und es ist das, was Sie später einem Vision-Modell übergeben werden.

Konvertieren Sie Ihre Rechnung von einem Bild in Text

Eine Bildschirmaufnahme einer Rechnung, die mit einem Smartphone aufgenommen wurde
Bild einer Rechnung, die mit einem Smartphone aufgenommen wurde

Eine PDF-Datei kann ein Bild enthalten. Zum Beispiel kann Ihr Mitarbeiter einen Schnappschuss einer Rechnung mit der Kamera seines Smartphones machen. Dieser wird dann als PDF gespeichert und an Ihre Buchhaltungsabteilung geschickt. Ihr Buchhaltungsteam ist dafür zuständig, die Daten aus dieser Rechnung zu extrahieren und sie fehlerfrei in Ihr Buchhaltungssystem zu übertragen. Der nächste Schritt besteht darin, dieses Bild mit einem Optischen Zeichenerkennungssystem in Text umzuwandeln. Eines der beliebtesten OCR-Systeme ist Tesseract. Tesseract ist in C und C++ geschrieben. Um Tesseract von unserem Python-Programm aus verwenden zu können, müssen wir eine Bindung wie PyTesseract verwenden. Eine Bindung ist eine Möglichkeit, eine Softwarebibliothek (hier Tesseract) aus einer Sprache heraus aufzurufen, in der sie nicht geschrieben ist (hier Python). Es gibt viele solcher Systeme, und ihre Ergebnisse sind sehr unterschiedlich, je nach der zugrundeliegenden Technologie und der Qualität des Scans des Dokuments, an dem sie arbeiten. Parseur erkennt transparent, ob es sich bei Ihrem Dokument um ein Bild handelt, und wandelt es intern automatisch in Text um. Sobald die Daten des Dokuments in Textform vorliegen, können sie extrahiert werden.

Extrahieren Sie den Text aus Ihrer Rechnung gemäß Ihrem Datenschema

Sobald sich Ihr PDF in Textform (oder durchsuchbarer Form) befindet, können Sie die Python-Bibliothek pdftotext verwenden, um die Daten aus der PDF-Datei als Text zu extrahieren. Hier ist ein Code-Snippet, um den Text aus einer PDF-Datei zu extrahieren:

import pdftotext

# Load your invoice
with open("invoice.pdf", "rb") as file_handle:
    pdf = pdftotext.PDF(file_handle)

# Iterate over all the pages
for page in pdf:
    print(page)

Nennen Sie dieses Skript convert_pdf_to_text.py und führen Sie es aus. Sie erhalten die Rechnung als Text in der Standardausgabe. Wenn Sie die Ausgabe in eine Datei umleiten möchten, können Sie Folgendes ausführen:

$ python convert_pdf_to_text.py > invoice.txt

pdftotext gibt Ihnen eine flache Zeichenfolge zurück, was für Kopffelder in Ordnung ist, für Tabellen jedoch hoffnungslos. Wenn Sie die Einzelposten benötigen, sollten Sie stattdessen auf pdfplumber zurückgreifen, da es die Koordinaten jedes Wortes beibehält und den Versuch einer Tabelle unternehmen kann:

import pdfplumber

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

    # Words with their positions on the page
    for word in page.extract_words():
        print(word["text"], word["x0"], word["top"])

    # And an attempt at the line-item table
    table = page.extract_table()
    if table:
        for row in table:
            print(row)

Lassen Sie das auf eine echte Lieferantenrechnung los, und Sie werden sehr oft feststellen, dass table gleich None ist. Das ist kein Fehler. Es ist das erste ehrliche Signal dafür, dass dieses Problem schwieriger ist, als es aussieht, und wir werden weiter unten darauf zurückkommen.

Nachdem Sie die Rechnung nun in Textform vorliegen haben, können Sie die gewünschten Daten mit einer beliebigen Kombination der folgenden Techniken extrahieren:

  • Sie können einen regulären Ausdruck verwenden, um die gewünschten Daten zu extrahieren. Reguläre Ausdrücke sind eine leistungsstarke Möglichkeit, Daten aus Text zu extrahieren, aber sie sind auch sehr fehleranfällig. Wenn sich das Rechnungsformat ändert, müssen Sie Ihren regulären Ausdruck aktualisieren. Außerdem sind reguläre Ausdrücke nicht sehr gut geeignet, um Daten aus Tabellen zu extrahieren.
  • Sie können ein visuelles Template-System verwenden, das idealerweise Dynamisches OCR und Zonale OCR nutzt. Dies ist eine fortschrittlichere Methode, um Daten aus Text zu extrahieren. Sie ist robuster als reguläre Ausdrücke, aber auch komplexer zu implementieren.
  • Sie können die Seite mit einem Schema an ein Vision-Modell übergeben und dieses das Dokument so lesen lassen, wie es ein Mensch tut. Das ist der Ansatz, der sich in den letzten zwei Jahren geändert hat, und er erhält unten seinen eigenen Abschnitt.

Lassen Sie uns Daten aus Ihrer Rechnung mit dem Python-Modul re für reguläre Ausdrücke extrahieren. Hier ist ein Code-Snippet, um die Rechnungsnummer aus Ihrer Rechnung zu extrahieren:

import re

# Load your invoice
with open("invoice.txt", "r") as file_handle:
    invoice = file_handle.read()

# Extract the invoice number
invoice_number = re.search(r"Invoice number: (\w+)", invoice).group(1)
print(invoice_number)

Nennen Sie dieses Skript extract.py und führen Sie es aus. Sie erhalten die Rechnungsnummer in der Standardausgabe:

$ python extract.py

Und Sie erhalten etwa Folgendes:

INV-1234

Warum Ihr Regex-Rechnungs-Parser abbricht

Ein Regex trifft auf eine Zeichenkette (String) zu. Eine Rechnung ist ein Bild. Alles, was schiefgeht, resultiert aus dieser Diskrepanz, und es geht auf einige wenige, vorhersehbare Arten schief:

  • Die Beschriftung hat sich verschoben. Ihr Muster ist an Invoice number: verankert und die neue Vorlage besagt Invoice #, oder der Wert steht in der nächsten Zeile anstatt in derselben.
  • extract_table gibt None zurück. Tabellenextraktoren suchen nach Begrenzungslinien. Die meisten Lieferantenrechnungen richten ihre Spalten mit Leerzeichen aus und zeichnen überhaupt keine Rahmen.
  • Der Text kommt in der falschen Reihenfolge an. Zweispaltige Layouts und schwebende Adressblöcke verschachteln sich, wenn die Seite in einen String komprimiert wird, sodass die Zeilen der Einzelposten durcheinander ankommen.
  • Die Tabelle geht über mehrere Seiten. Die Zeilen zwei bis neun befinden sich auf Seite eins, zehn bis vierzehn auf Seite zwei, wobei die Spaltenüberschriften dazwischen wiederholt werden und eine Zwischensummenzeile vorgibt, ein Artikel zu sein.
  • Drei Zahlen sehen alle wie die Gesamtsumme aus. Zwischensumme, Gesamtsumme, fälliger Betrag und vorgetragener Saldo. Den größten Wert auszuwählen, ist bei jeder Rechnung mit einer Gutschrift falsch.
  • Der Scan ist ein Foto. Die OCR liest eine verschmierte 8 als eine 3 und die nachgelagerten Systeme merken nichts davon, weil 3 eine völlig gültige Ziffer ist.
  • Verbundene Zellen und mehrzeilige Beschreibungen. Eine Produktbeschreibung erstreckt sich über drei Zeilen und Ihre Zeilentrennungslogik macht daraus drei Artikel ohne Preise.

Keines dieser Probleme ist mit einem besseren regulären Ausdruck lösbar. Es handelt sich durchweg um Layout-Probleme, die sich als String-Probleme tarnen. Das ist der Punkt, an dem die meisten Leute entweder damit beginnen, eine Vorlage pro Lieferant zu schreiben (was endlos wächst), oder den Ansatz ändern.

Der Ansatz für 2026 – ein Vision-Modell und ein Schema

Die nützliche Veränderung besteht darin, dass Sie die Seite nicht mehr in Text komprimieren müssen, bevor Sie daraus extrahieren. Ein Vision-Modell betrachtet die gerenderte Rechnung, sodass das Verschieben der Rechnungsnummer durch einen Lieferanten kein kritisches Ereignis mehr ist. Was Sie bereitstellen, ist kein Muster, sondern das Schema, das Sie zu Beginn dieses Artikels geschrieben haben.

Beschränken Sie die Ausgabe, damit Sie jedes Mal dieselben Schlüssel erhalten. Pydantic plus ein Modus für strukturierte Ausgaben, wie z.B. OpenAI's structured outputs, erledigt das für Sie:

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]

# Render the PDF page to an image, send it to a vision model,
# and require the response to match the Invoice schema.
# The model fills the fields. It does not get to invent the shape.

Das ist tatsächlich der Großteil des Extraktionsproblems gelöst, und aus diesem Grund hat sich dieser Ansatz so schnell verbreitet. Er führt auch eine neue Fehlerquelle ein, die Regex nie hatte: Ein Regex, der die Rechnungsnummer nicht finden kann, gibt None zurück, während ein Modell, das sie nicht findet, manchmal eine plausible erfindet. Die Regel, die Sie absichert, ist einfach: Das Modell macht einen Vorschlag, Ihr Code verifiziert.

Wenn Sie das Modell lieber nicht selbst betreiben möchten, wird dieselbe Funktionalität als Managed Service von den Cloud-Anbietern angeboten, etwa in Azure AI Document Intelligence und Amazon Textract's AnalyzeExpense, die beide Kopffelder und Einzelposten separat zurückgeben. Wir haben in AI versus rule-based PDF parsers beschrieben, wie sich dieser zugrunde liegende Ansatz von regelbasiertem Parsing unterscheidet, und wie das speziell bei Rechnungen aussieht, finden Sie unter vision AI invoice processing.

Die Validierungsschicht, die Sie selbst schreiben müssen

Egal, was Ihr JSON produziert hat, diese Prüfungen gehören in Ihren Code, nicht in den Konfidenz-Score des Extraktors. Sie sind günstig, deterministisch und fangen die Fehler ab, die Geld kosten:

  1. Zwischensumme + Steuern + Versand - Rabatt ergibt exakt die Gesamtsumme (auf den Cent genau).
  2. Die Beträge der Einzelposten summieren sich zur Zwischensumme. Tun sie das nicht, haben Sie eine Zeile übersehen oder eine erfunden.
  3. Jedes Menge * Einzelpreis entspricht seinem eigenen Betrag.
  4. Das Datum lässt sich parsen und liegt nicht in der Zukunft.
  5. Die Rechnungsnummer wurde für diesen Lieferanten nicht bereits bezahlt. Doppelzahlungen sind der teuerste Fehler in der Kreditorenbuchhaltung.
  6. Der Lieferantenname ist mit einem Datensatz in Ihrem Lieferantenstamm verknüpft.
  7. Die Zahlungsverkehrsbankdaten stimmen mit denen überein, die für diesen Lieferanten bereits hinterlegt sind. Eine Änderung hier ist eine Betrugsprüfung, keine Datenprüfung.
  8. Die Währung ist eine, in der Sie auch tatsächlich handeln.
  9. Die Bestellnummer (Purchase Order Number) existiert, und ihre Mengen und Preise stimmen überein, wenn Sie einen 2-Wege- oder 3-Wege-Abgleich (Two-way or three-way matching) durchführen.
  10. Jedes Pflichtfeld ist vorhanden und nicht leer.

Alles, was fehlschlägt, geht an eine Person, nicht in das Hauptbuch:

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

Zehn Zeilen Arithmetik erfassen mehr echte Probleme als noch so viel Prompt-Tuning.

Was ist mit invoice2data und den anderen Bibliotheken?

invoice2data verdient eine ehrliche Erwähnung, da es für viele Leute das erste Ergebnis ist und es sich um ein wirklich gutes Stück Software handelt. Es ist ein Kommandozeilen-Tool und eine Python-Bibliothek, die Rechnungen mit YAML-Vorlagen abgleicht, die Sie pro Lieferant schreiben, wobei sich die Abgleichsregeln in der Versionskontrolle und nicht in Ihrem Code verbergen. Wenn Sie ein Dutzend Lieferanten haben, die ihr Layout nie ändern, wird es Ihnen jahrelang gute Dienste leisten.

Die Grenze liegt im Design, nicht in der Qualität. Eine Vorlage pro Lieferant bedeutet, dass Ihr Wartungsaufwand mit Ihrer Lieferantenliste wächst und die Vorlagen genau aus den oben genannten Gründen kaputtgehen. Irgendwo zwischen zwanzig und dreißig aktiven Layouts leistet die Person, die die Vorlagen pflegt, mehr Arbeit als die Person, die die Rechnungen früher abgetippt hat.

Die gleiche Logik gilt für den Rest des Bibliotheken-Regals. pdfplumber, PyMuPDF, pdftotext und pytesseract sind in ihren eigentlichen Aufgaben – dem Extrahieren von Zeichen und Koordinaten von einer Seite – alle hervorragend. Keine von ihnen war je dazu gedacht zu wissen, welche Zahl die Gesamtsumme ist. Wir vergleichen die breitere Auswahl in unserer Übersicht über die best PDF parsers und die best data extraction APIs.

Sammeln Sie die extrahierten Daten

Mit Python können Sie die Rechnungsdateien in einem bestimmten Ordner durchlaufen und die Daten aus diesen Dateien extrahieren. Nehmen wir an, wir extrahieren die Rechnungsnummer und den Gesamtbetrag und geben das Ergebnis im CSV-Format aus:

import os
import re

import pdftotext

# Iterate over all the PDF files in the folder
for filename in os.listdir("invoices/"):
    if not filename.endswith(".pdf"):
        continue

    # Load your invoice
    with open("invoices/" + filename, "rb") as file_handle:
        pdf = pdftotext.PDF(file_handle)

    # Print the CSV column header
    print("InvoiceNumber,TotalAmount")

    # Iterate over all the pages
    for page in pdf:
        # Extract the invoice number
        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=",")

Nennen Sie dieses Skript extract_to_csv.py und führen Sie es aus. Sie erhalten die Rechnungsnummer und den Gesamtbetrag in der Standardausgabe, die Sie in eine CSV-Datei umleiten können, die Sie später mit Ihrer bevorzugten Tabellenkalkulationssoftware wie Excel öffnen können:

$ python extract_to_csv.py > invoices.csv

Ein Ordner mit CSV-Dateien ist der Punkt, an dem die meisten Rechnungs-Skripte enden, und es ist auch der Ort, an dem die ehrliche Buchhaltung beginnt. Irgendjemand muss diese Dateien immer noch importieren, die Lieferanten zuordnen, den vom Buchhaltungssystem abgelehnten Zeilen nachgehen und herausfinden, was mit der Rechnung zu tun ist, die nachts um 2 Uhr bei der Validierung durchgefallen ist. Diese Arbeit taucht in Ihrem Skript nicht auf, und sie erscheint auch nicht auf Ihrer Token-Rechnung.

Wann Sie aufhören sollten, selbst zu bauen

Hier ist der Teil, den die meisten Anbieter überspringen, weshalb wir ihn zuerst sagen werden. Wenn Sie eine Handvoll beständiger Lieferanten haben, einen Ingenieur, der eine Pipeline überwachen kann, und niemanden, der auf die Daten wartet, dann schreiben Sie das Skript. Ein Vision-Modell plus ein Schema plus die oben genannten zehn Zeilen Validierung werden Sie für sehr wenig Geld weit bringen, und Sie werden jeden Teil davon verstehen.

Die Rechnung für das Selberbauen kommt später, und zwar nie bei der Extraktion. Sie taucht in den Teilen auf, die niemand als Prototyp baut:

  • Die Ausnahme-Warteschlange (Exception queue). Ihr Kreditoren-Team (AP team) benötigt einen Bildschirm, auf dem das Anklicken eines Feldes dieses auf der Rechnung hervorhebt, damit sie den Fehler in vier Sekunden statt in vierzig beheben können. Das ist ein Produkt, kein Skript.
  • Lieferantenabgleich (Vendor matching). "ACME Ltd", "Acme Limited" und "ACME LTD." sind ein und derselbe Lieferant, und das Hauptbuch wird keine drei akzeptieren.
  • Duplikaterkennung. Dieselbe Rechnung kommt am Dienstag als E-Mail-Anhang und am Freitag als Kontoauszugs-PDF an.
  • Der Zustandsautomat (The state machine). Warteschlangen, Wiederholungen, Teilfehler und das Wissen darüber, welche der 300 Rechnungen von letzter Nacht tatsächlich durchgekommen sind.
  • Der Audit-Trail. Was wurde extrahiert, was hat ein Mensch geändert, wer hat es genehmigt und wann. Die Finanzabteilung wird danach fragen, meist während einer Prüfung.
  • Alles nach dem JSON. Feldzuordnung in das Buchhaltungssystem, Sachkontenkodierung (GL coding), Bestellabgleich und die Umgangsweise mit abgelehnten Zeilen.

Die klaren Signale, dass es Zeit ist zu kaufen statt zu bauen, sind folgende: Sie haben in etwa die Marke von zwanzig bis dreißig aktiven Lieferantenlayouts überschritten. Sie benötigen Einzelposten, nicht nur Kopffelder. Mehr als eine Handvoll Ihrer Rechnungen treffen als Scans ein. Ihr AP-Team, nicht Ihr Entwicklerteam, muss die Fehler beheben. Fehlgeschlagene Extraktionen verzögern Zahlungen. Oder – was am häufigsten vorkommt – die Person, die den Parser pflegt, hat aufgehört, an etwas anderem zu arbeiten.

Wie Parseur damit umgeht

Parseur ist ein Dokumenten-Parser, der den gesamten Zyklus abdeckt, nicht nur den Extraktionsschritt. Rechnungen kommen an einer speziellen Postfachadresse an, über die API oder aus einem überwachten Ordner. Die Vision AI engine liest PDFs, Scans und Fotos, und die Text AI-Engine liest E-Mails und Textdokumente. Felder werden benannt und typisiert ausgegeben, und Einzelposten erscheinen als Zeilen. Es müssen keine Vorlagen geschrieben werden und es gibt nichts zu warten, wenn ein Lieferant seine Rechnung neu gestaltet.

Was Sie zusätzlich zum JSON erhalten, ist die Hälfte, vor der dieser Artikel Sie gewarnt hat. Extrahierte Daten können an Ort und Stelle überprüft und korrigiert werden, sodass eine Person aus der Kreditorenbuchhaltung eine falsch gelesene Summe korrigiert, ohne ein Ticket eröffnen zu müssen. Korrekturen fließen in die Extraktion zurück. Und die Daten gelangen dorthin, wo sie gebraucht werden, durch die direct webhook integration, Make, Zapier oder Microsoft Power Automate, oder direkt aus der API als JSON.

Wenn Sie sehen möchten, welche Felder wir standardmäßig aus Rechnungen extrahieren, finden Sie dies dokumentiert auf unserer invoice OCR page, und der breitere Workflow wird unter invoice data capture behandelt.

Erstellen Sie Ihr kostenloses Konto
Sparen Sie Zeit und Mühe mit Parseur. Automatisieren Sie Ihre Dokumente.

Fazit

Das Extrahieren von Rechnungsdaten aus einem PDF mit Python ist ein gelöstes Problem bei etwa einhundert Rechnungen und ein ungelöstes bei zehntausend. Der Code ist nicht das, was sich zwischen diesen beiden Zahlen ändert. Was sich ändert, ist, wie viele Lieferantenlayouts Sie stillschweigend zu warten bereit sind und wer alarmiert wird, wenn sich eines davon verschiebt.

Schreiben Sie das Skript. Es lohnt sich wirklich, es einmal zu tun, und sei es nur, um genau herauszufinden, welcher der sieben oben genannten Fehlermodi Sie zuerst trifft. Entscheiden Sie dann ehrlich, ob die nächsten sechs Monate Ihrer Zeit am besten auf den achten Modus verwendet werden. Wenn die Antwort nein lautet, Parseur macht das seit 2016 und nimmt Ihnen den Ordner gerne ab.

Zuletzt aktualisiert am

Jetzt starten

Bereit, Ihre Datenextraktion
aus Dokumenten zu automatisieren?

Kostenlos in wenigen Minuten starten und sehen, wie Parseur in Ihren Workflow passt.

Kein Modelltraining nötig
Automatisiert die Dateneingabe aus jedem Dokument
Von der Web-App bis zur API. Wächst mit Ihnen.

Häufig gestellte Fragen

Die Fragen, die Entwickler tatsächlich stellen, sobald das erste Rechnungs-Skript läuft und der zweite Lieferant es kaputt gemacht hat.

Lesen Sie den Text aus dem PDF mit einer Bibliothek wie pdfplumber oder pdftotext aus und ziehen Sie dann benannte Felder aus diesem Text. Für nativ digitale PDFs ist das eine zweistufige Aufgabe. Bei Scans benötigen Sie zunächst einen OCR-Durchlauf, um das Bild in Text umzuwandeln. Der Teil, der entscheidet, ob es in der Produktion funktioniert, ist nicht das Auslesen, sondern wie Sie von einer Textwand zu Rechnungsnummer, Datum, Lieferant und Einzelposten gelangen, wenn jeder Lieferant sie anders anordnet.

invoice2data ist ein Open-Source-Kommandozeilen-Tool und eine Python-Bibliothek, die Felder aus Rechnungen mithilfe von YAML-Vorlagen extrahiert, die Sie pro Lieferant schreiben. Es eignet sich gut, wenn Sie eine kleine, stabile Gruppe von Lieferanten haben und die Zuordnungslogik lieber in der Versionskontrolle als in Ihrem Code haben möchten. Es ist nicht mehr geeignet, wenn das Schreiben und Pflegen einer Vorlage pro Lieferant mehr kostet als das manuelle Abtippen, das es ersetzt hat.

Behandeln Sie die Tabelle mit den Einzelposten als separate Extraktion von den Kopffeldern und rekonstruieren Sie sie seitenübergreifend, bevor Sie sie parsen. Der extract_table-Befehl von pdfplumber funktioniert bei sauber linierten Tabellen und liefert bei randlosen Tabellen – wie bei den meisten Lieferantenrechnungen – kein Ergebnis. Das zuverlässige Muster besteht darin, die Spaltengrenzen einmal pro Lieferantenlayout zu erkennen, sie über Seitenumbrüche hinweg zu übertragen, wiederholte Kopfzeilen zu verwerfen und dann zu überprüfen, ob die extrahierten Zeilen die Zwischensumme ergeben. Tun sie das nicht, haben Sie eine Zeile übersehen.

Mit deterministischen Prüfungen in Ihrem eigenen Code, niemals allein mit der Konfidenz des Extraktors. Der Kern besteht aus Arithmetik und Identität. Bestätigen Sie, dass Zwischensumme plus Steuer plus Versand abzüglich Rabatt genau die Gesamtsumme ergibt, dass sich die Einzelposten zur Zwischensumme addieren, dass das Datum verarbeitet wird und nicht in der Zukunft liegt, dass die Rechnungsnummer für diesen Lieferanten nicht bereits bezahlt wurde, dass der Lieferant in Ihrem Lieferantenstamm existiert und dass die Währung eine von Ihnen erwartete ist. Alles, was fehlschlägt, geht an einen Menschen statt in das Hauptbuch.

Wenn die Extraktion nicht mehr der schwierige Teil ist. Der Aufruf eines Vision-Modells ist günstig und schnell als Prototyp umsetzbar. Wenn Sie also eine Handvoll beständiger Lieferanten und jemanden haben, der die Pipeline überwachen kann, bauen Sie sie selbst. Die Rechnung kommt später – in der Warteschlangen- und Wiederholungslogik, dem Ausnahme-Prüfbildschirm, den Ihr Kreditoren-Team benötigt, der Duplikaterkennung, dem Lieferantenabgleich, dem Audit-Trail und der Buchhaltungsintegration. Zählen Sie diese Aspekte, bevor Sie die Preise pro Seite vergleichen.

Ja, aber ein Scan benötigt einen OCR-Durchlauf, bevor eine der Textbibliotheken etwas erkennen kann. Eine abfotografierte oder gescannte Rechnung ist ein Bild verpackt in einem PDF, daher geben pdfplumber und pdftotext hierfür einen leeren String zurück. Der übliche Open-Source-Weg ist Tesseract über die pytesseract-Bindung, nachdem das Bild geradegerichtet und bereinigt wurde. Moderne Vision-Modelle überspringen diesen Schritt komplett und lesen das Bild direkt.

Es gibt keine Rechnungsbibliothek, nur PDF-Bibliotheken plus Ihre eigene Logik. pdfplumber ist die übliche erste Wahl, da es Wörter mit ihren Koordinaten freilegt und einen Tabellenextraktor hat. PyMuPDF ist bei großen Stapeln schneller. pdftotext ist die kleinste Lösung, die funktioniert, wenn Sie nur den Rohtext benötigen. pytesseract verarbeitet Scans. Jede dieser Bibliotheken liefert Ihnen Text oder Rahmen. Keine von ihnen sagt Ihnen, welche Zahl der Gesamtbetrag ist.

Weil ein Regex auf eine Zeichenkette zutrifft und eine Rechnung ein Bild ist. Ihr Muster ist an eine Beschriftung, einen Zeilenumbruch oder eine Spaltenposition verankert, die in der neuen Vorlage des Lieferanten verschoben wurde. Rechnungen sind teilstrukturierte visuelle Dokumente, daher sind die Dinge, die Ihren Parser stören, eher Layout-Probleme als String-Probleme. Tabellen, die über mehrere Seiten gehen, wiederholte Kopfzeilen, verbundene Zellen und der Unterschied zwischen Zwischensumme, Gesamtsumme und fälligem Betrag lassen sich nicht mit einem besseren regulären Ausdruck beheben.

Ja, und es ist mittlerweile der kürzeste Weg von einem PDF zu strukturiertem JSON, aber nur mit einem Schema und einem Validator darum herum. Ein Vision-Modell liest die Rechnung so, wie es ein Mensch tut, sodass eine Layoutänderung durch einen Lieferanten kein kritisches Ereignis mehr ist. Beschränken Sie die Ausgabe mit einem JSON-Schema, z.B. mit OpenAI structured outputs oder einem Pydantic-Modell, damit Sie jedes Mal dieselben Schlüssel erhalten. Überprüfen Sie dann die Arithmetik selbst. Ein Modell, das die Rechnungsnummer nicht finden kann, wird manchmal eine plausible erfinden.

Die Genauigkeit hängt vom Feld und vom Scan ab, nicht vom Produkt, behandeln Sie also jeden prozentualen Genauigkeitswert aus den Schlagzeilen als Marketing. Gedruckte Summen und Rechnungsnummern auf einem sauberen, nativ digitalen PDF kommen fast perfekt zurück. Dieselben Felder auf einem abfotografierten, schiefen und kontrastarmen Scan sind die Stellen, an denen Ziffern verwechselt werden und ein falsches Zeichen echtes Geld kostet. Die Kennzahl, die es zu messen gilt, ist nicht die Zeichengenauigkeit, sondern wie viele Rechnungen Ihr Buchhaltungssystem erreichen, ohne dass ein Mensch sie berühren muss.

Sie hören auf, für jeden Lieferanten etwas Eigenes zu schreiben. Jeder Ansatz, der eine Vorlage, ein Regex-Set oder eine Koordinatenkarte für jeden Kreditor benötigt, wächst linear mit Ihrer Lieferantenliste und verringert ab etwa zwanzig bis dreißig aktiven Layouts niemandes Arbeitsaufwand mehr. Ein Modell, das das Dokument visuell liest, ist systembedingt formatunabhängig, weshalb Layoutabweichungen keine Wartungsereignisse mehr darstellen. Was weiterhin Ihre Aufmerksamkeit erfordert, ist die Ausnahme-Warteschlange, und das ist eher ein Workflow- als ein Extraktionsproblem.

Das Schreiben einer CSV-Datei erfordert nur wenige Zeilen Python-Code und ist die einfache Hälfte. Die schwierige Hälfte besteht darin, die Daten in das System zu bekommen, das die Rechnung bezahlt. Das bedeutet, dass Sie Ihre Feldnamen auf dessen Schema abbilden, Lieferanten mit bestehenden Datensätzen abgleichen, vom System abgelehnte Zeilen handhaben und fehlgeschlagene Aufrufe wiederholen müssen. Planen Sie diese Hälfte von Anfang an ein, denn ein Ordner voller CSV-Dateien, die immer noch jemand von Hand importiert, hat niemandem einen Nachmittag gerettet.