Formularparsen mit Document AI (Python)

1. Einführung

In diesem Codelab erfahren Sie, wie Sie mit dem Document AI-Formularparser ein handschriftliches Formular mit Python parsen.

Als Beispiel dient ein einfaches medizinisches Aufnahmeformular. Das Verfahren funktioniert jedoch mit jedem allgemeinen Formular, das von DocAI unterstützt wird.

Voraussetzungen

Dieses Codelab baut auf Inhalten auf, die in anderen Document AI-Codelabs vorgestellt werden.

Wir empfehlen Ihnen, die folgenden Codelabs zu absolvieren, bevor Sie fortfahren.

Lerninhalte

  • So parsen und extrahieren Sie Daten mit dem Document AI-Formularparser aus einem gescannten Formular.

Voraussetzungen

Umfrage

Wie werden Sie diese Anleitung verwenden?

Nur lesen Lesen und Übungen durchführen

Wie würden Sie Ihre Erfahrung mit Python bewerten?

Anfänger Mittelstufe Fortgeschrittene

Wie würden Sie Ihre Erfahrungen mit Google Cloud-Diensten bewerten?

Anfänger Mittelstufe Fortgeschritten

2. Einrichtung und Anforderungen

In diesem Codelab wird davon ausgegangen, dass Sie die im Document AI OCR-Codelab aufgeführten Einrichtungsschritte für Document AI abgeschlossen haben.

Führen Sie die folgenden Schritte aus, bevor Sie fortfahren:

Außerdem sollten Sie Pandas installieren, eine Open-Source-Bibliothek für Python zur Datenanalyse.

pip3 install --upgrade pandas

3. Formularparser-Prozessor erstellen

Sie müssen zuerst eine Formularparser-Prozessorinstanz erstellen, die Sie in der Document AI Platform für diese Anleitung verwenden können.

  1. Rufen Sie in der Console die Document AI Platform-Übersicht auf.
  2. Klicken Sie auf Prozessor erstellen und wählen Sie FormularparserProzessoren aus.
  3. Geben Sie einen Prozessornamen an und wählen Sie Ihre Region aus der Liste aus.
  4. Klicken Sie auf Erstellen, um den Prozessor zu erstellen.
  5. Kopieren Sie Ihre Prozessor-ID. Sie müssen sie später in Ihrem Code verwenden.

Prozessor in der Cloud Console testen

Sie können Ihren Prozessor in der Console testen, indem Sie ein Dokument hochladen. Klicken Sie auf Dokument hochladen und wählen Sie ein zu parsendes Formular aus. Sie können dieses Musterformular herunterladen und verwenden, wenn Sie kein eigenes Formular haben.

Aufnahmeformular

Die Ausgabe sollte so aussehen: Geparstes Formular

4. Beispielformular herunterladen

Wir haben ein Beispieldokument mit einem einfachen medizinischen Aufnahmeformular.

Sie können die PDF-Datei über den folgenden Link herunterladen. Laden Sie es dann in die Cloud Shell-Instanz hoch.

Alternativ können Sie sie mit gsutil aus unserem öffentlichen Google Cloud Storage-Bucket herunterladen.

gsutil cp gs://cloud-samples-data/documentai/codelabs/form-parser/intake-form.pdf .

Prüfen Sie mit dem folgenden Befehl, ob die Datei in die Cloud Shell heruntergeladen wurde:

ls -ltr intake-form.pdf

5. Schlüssel/Wert-Paare aus Formularen extrahieren

In diesem Schritt verwenden Sie die Onlineverarbeitungs-API, um den zuvor erstellten Formularparser-Prozessor aufzurufen. Anschließend extrahieren Sie die im Dokument gefundenen Schlüssel/Wert-Paare.

Über die Onlineverarbeitung wird ein einzelnes Dokument gesendet. Anschließend wird auf die Antwort gewartet. Sie können auch die Batchverarbeitung verwenden, wenn Sie mehrere Dateien senden möchten oder die Dateigröße die maximale Seitenzahl für die Onlineverarbeitung überschreitet. Weitere Informationen dazu finden Sie im OCR-Codelab.

Der Code zum Senden einer Verarbeitungsanfrage ist für jeden Prozessortyp identisch, mit Ausnahme der Prozessor-ID.

Das Antwortobjekt Document enthält eine Liste der Seiten aus dem Eingabedokument.

Jedes page-Objekt enthält eine Liste der Formularfelder und ihrer Positionen im Text.

Der folgende Code durchläuft alle Seiten und extrahiert alle Schlüssel, Werte und Konfidenzwerte. Das sind strukturierte Daten, die einfacher in Datenbanken gespeichert oder in anderen Anwendungen verwendet werden können.

Erstellen Sie eine Datei mit dem Namen form_parser.py und verwenden Sie den folgenden Code.

form_parser.py

import pandas as pd
from google.cloud import documentai_v1 as documentai


def online_process(
    project_id: str,
    location: str,
    processor_id: str,
    file_path: str,
    mime_type: str,
) -> documentai.Document:
    """
    Processes a document using the Document AI Online Processing API.
    """

    opts = {"api_endpoint": f"{location}-documentai.googleapis.com"}

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # The full resource name of the processor, e.g.:
    # projects/project-id/locations/location/processor/processor-id
    # You must create new processors in the Cloud Console first
    resource_name = documentai_client.processor_path(project_id, location, processor_id)

    # Read the file into memory
    with open(file_path, "rb") as image:
        image_content = image.read()

        # Load Binary Data into Document AI RawDocument Object
        raw_document = documentai.RawDocument(
            content=image_content, mime_type=mime_type
        )

        # Configure the process request
        request = documentai.ProcessRequest(
            name=resource_name, raw_document=raw_document
        )

        # Use the Document AI client to process the sample form
        result = documentai_client.process_document(request=request)

        return result.document


def trim_text(text: str):
    """
    Remove extra space characters from text (blank, newline, tab, etc.)
    """
    return text.strip().replace("\n", " ")


PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "YOUR_PROJECT_LOCATION"  # Format is 'us' or 'eu'
PROCESSOR_ID = "FORM_PARSER_ID"  # Create processor in Cloud Console

# The local file in your current working directory
FILE_PATH = "intake-form.pdf"
# Refer to https://cloud.google.com/document-ai/docs/processors-list
# for supported file types
MIME_TYPE = "application/pdf"

document = online_process(
    project_id=PROJECT_ID,
    location=LOCATION,
    processor_id=PROCESSOR_ID,
    file_path=FILE_PATH,
    mime_type=MIME_TYPE,
)

names = []
name_confidence = []
values = []
value_confidence = []

for page in document.pages:
    for field in page.form_fields:
        # Get the extracted field names
        names.append(trim_text(field.field_name.text_anchor.content))
        # Confidence - How "sure" the Model is that the text is correct
        name_confidence.append(field.field_name.confidence)

        values.append(trim_text(field.field_value.text_anchor.content))
        value_confidence.append(field.field_value.confidence)

# Create a Pandas Dataframe to print the values in tabular format.
df = pd.DataFrame(
    {
        "Field Name": names,
        "Field Name Confidence": name_confidence,
        "Field Value": values,
        "Field Value Confidence": value_confidence,
    }
)

print(df)

Führen Sie den Code jetzt aus. Der Text sollte extrahiert und in der Console ausgegeben werden.

Wenn Sie unser Beispieldokument verwenden, sollte die folgende Ausgabe angezeigt werden:

$ python3 form_parser.py
                                           Field Name  Field Name Confidence                                        Field Value  Field Value Confidence
0                                            Phone #:               0.999982                                     (906) 917-3486                0.999982
1                                  Emergency Contact:               0.999972                                         Eva Walker                0.999972
2                                     Marital Status:               0.999951                                             Single                0.999951
3                                             Gender:               0.999933                                                  F                0.999933
4                                         Occupation:               0.999914                                  Software Engineer                0.999914
5                                        Referred By:               0.999862                                               None                0.999862
6                                               Date:               0.999858                                            9/14/19                0.999858
7                                                DOB:               0.999716                                         09/04/1986                0.999716
8                                            Address:               0.999147                                     24 Barney Lane                0.999147
9                                               City:               0.997718                                             Towaco                0.997718
10                                              Name:               0.997345                                       Sally Walker                0.997345
11                                             State:               0.996944                                                 NJ                0.996944
...

6. Tabellen parsen

Mit dem Formularparser lassen sich auch Daten aus Tabellen in Dokumenten extrahieren. In diesem Schritt laden wir ein neues Beispieldokument herunter und extrahieren Daten aus der Tabelle. Da wir die Daten in Pandas laden, können sie mit einem einzigen Methodenaufruf in eine CSV-Datei und viele andere Formate ausgegeben werden.

Beispielformular mit Tabellen herunterladen

Wir haben ein Beispieldokument mit einem Beispielformular und einer Tabelle.

Sie können die PDF-Datei über den folgenden Link herunterladen. Laden Sie es dann in die Cloud Shell-Instanz hoch.

Alternativ können Sie sie mit gsutil aus unserem öffentlichen Google Cloud Storage-Bucket herunterladen.

gsutil cp gs://cloud-samples-data/documentai/codelabs/form-parser/form_with_tables.pdf .

Prüfen Sie mit dem folgenden Befehl, ob die Datei in die Cloud Shell heruntergeladen wurde:

ls -ltr form_with_tables.pdf

Tabellendaten extrahieren

Die Verarbeitungsanfrage für Tabellendaten ist genau dieselbe wie für das Extrahieren von Schlüssel/Wert-Paaren. Der Unterschied besteht darin, aus welchen Feldern in der Antwort wir die Daten extrahieren. Tabellendaten werden im Feld pages[].tables[] gespeichert.

In diesem Beispiel werden Informationen aus den Tabellenüberschriften und ‑zeilen für jede Tabelle und Seite extrahiert, dann wird die Tabelle ausgegeben und als CSV-Datei gespeichert.

Erstellen Sie eine Datei mit dem Namen table_parsing.py und verwenden Sie den folgenden Code.

table_parsing.py

# type: ignore[1]
"""
Uses Document AI online processing to call a form parser processor
Extracts the tables and data in the document.
"""
from os.path import splitext
from typing import List, Sequence

import pandas as pd
from google.cloud import documentai


def online_process(
    project_id: str,
    location: str,
    processor_id: str,
    file_path: str,
    mime_type: str,
) -> documentai.Document:
    """
    Processes a document using the Document AI Online Processing API.
    """

    opts = {"api_endpoint": f"{location}-documentai.googleapis.com"}

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # The full resource name of the processor, e.g.:
    # projects/project-id/locations/location/processor/processor-id
    # You must create new processors in the Cloud Console first
    resource_name = documentai_client.processor_path(project_id, location, processor_id)

    # Read the file into memory
    with open(file_path, "rb") as image:
        image_content = image.read()

        # Load Binary Data into Document AI RawDocument Object
        raw_document = documentai.RawDocument(
            content=image_content, mime_type=mime_type
        )

        # Configure the process request
        request = documentai.ProcessRequest(
            name=resource_name, raw_document=raw_document
        )

        # Use the Document AI client to process the sample form
        result = documentai_client.process_document(request=request)

        return result.document


def get_table_data(
    rows: Sequence[documentai.Document.Page.Table.TableRow], text: str
) -> List[List[str]]:
    """
    Get Text data from table rows
    """
    all_values: List[List[str]] = []
    for row in rows:
        current_row_values: List[str] = []
        for cell in row.cells:
            current_row_values.append(
                text_anchor_to_text(cell.layout.text_anchor, text)
            )
        all_values.append(current_row_values)
    return all_values


def text_anchor_to_text(text_anchor: documentai.Document.TextAnchor, text: str) -> str:
    """
    Document AI identifies table data by their offsets in the entirety of the
    document's text. This function converts offsets to a string.
    """
    response = ""
    # If a text segment spans several lines, it will
    # be stored in different text segments.
    for segment in text_anchor.text_segments:
        start_index = int(segment.start_index)
        end_index = int(segment.end_index)
        response += text[start_index:end_index]
    return response.strip().replace("\n", " ")


PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "YOUR_PROJECT_LOCATION"  # Format is 'us' or 'eu'
PROCESSOR_ID = "FORM_PARSER_ID"  # Create processor before running sample

# The local file in your current working directory
FILE_PATH = "form_with_tables.pdf"
# Refer to https://cloud.google.com/document-ai/docs/file-types
# for supported file types
MIME_TYPE = "application/pdf"

document = online_process(
    project_id=PROJECT_ID,
    location=LOCATION,
    processor_id=PROCESSOR_ID,
    file_path=FILE_PATH,
    mime_type=MIME_TYPE,
)

header_row_values: List[List[str]] = []
body_row_values: List[List[str]] = []

# Input Filename without extension
output_file_prefix = splitext(FILE_PATH)[0]

for page in document.pages:
    for index, table in enumerate(page.tables):
        header_row_values = get_table_data(table.header_rows, document.text)
        body_row_values = get_table_data(table.body_rows, document.text)

        # Create a Pandas Dataframe to print the values in tabular format.
        df = pd.DataFrame(
            data=body_row_values,
            columns=pd.MultiIndex.from_arrays(header_row_values),
        )

        print(f"Page {page.page_number} - Table {index}")
        print(df)

        # Save each table as a CSV file
        output_filename = f"{output_file_prefix}_pg{page.page_number}_tb{index}.csv"
        df.to_csv(output_filename, index=False)

Führen Sie den Code jetzt aus. Der Text sollte extrahiert und in der Console ausgegeben werden.

Wenn Sie unser Beispieldokument verwenden, sollte die folgende Ausgabe angezeigt werden:

$ python3 table_parsing.py
Page 1 - Table 0
     Item    Description
0  Item 1  Description 1
1  Item 2  Description 2
2  Item 3  Description 3
Page 1 - Table 1
  Form Number:     12345678
0   Form Date:   2020/10/01
1        Name:   First Last
2     Address:  123 Fake St

Außerdem sollten sich im Verzeichnis, in dem Sie den Code ausführen, zwei neue CSV-Dateien befinden.

$ ls
form_with_tables_pg1_tb0.csv form_with_tables_pg1_tb1.csv table_parsing.py

7. Glückwunsch

Gute Arbeit. Sie haben mit der Document AI API Daten aus einem handschriftlich ausgefüllten Formular extrahiert. Wir empfehlen Ihnen, auch andere Formulardokumente auszuprobieren.

Bereinigen

So vermeiden Sie, dass Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen in Rechnung gestellt werden:

  • Wechseln Sie in der Cloud Console zur Seite Ressourcen verwalten.
  • Wählen Sie in der Projektliste Ihr Projekt aus und klicken Sie auf „Löschen“.
  • Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf „Beenden“, um das Projekt zu löschen.

Weitere Informationen

In diesen Codelabs erfahren Sie mehr über Document AI.

Ressourcen

Lizenz

Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.