Analisi di moduli con Document AI (Python)

1. Introduzione

In questo codelab imparerai a utilizzare l'analizzatore sintattico di moduli di Document AI per analizzare un modulo scritto a mano con Python.

Utilizzeremo un semplice modulo di assunzione medica come esempio, ma questa procedura funzionerà con qualsiasi modulo generalizzato supportato da DocAI.

Prerequisiti

Questo codelab si basa sui contenuti presentati in altri codelab di Document AI.

Ti consigliamo di completare i seguenti codelab prima di procedere.

Cosa imparerai a fare

  • Come analizzare ed estrarre i dati da un modulo scansionato utilizzando l'analizzatore sintattico di moduli di Document AI.

Che cosa ti serve

  • Un progetto Google Cloud
  • Un browser, ad esempio Chrome o Firefox
  • Conoscenza di Python 3

Sondaggio

Come utilizzerai questo tutorial?

Solo lettura Leggilo e completa gli esercizi

Come valuteresti la tua esperienza con Python?

Principiante Livello intermedio Eccellente

Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Livello intermedio Eccellente

2. Configurazione e requisiti

Questo codelab presuppone che tu abbia completato i passaggi di configurazione di Document AI elencati nel Codelab OCR di Document AI.

Completa i seguenti passaggi prima di procedere:

Dovrai anche installare Pandas, una libreria di analisi dei dati open source per Python.

pip3 install --upgrade pandas

3. Crea un processore dell'analizzatore sintattico di moduli

Devi prima creare un'istanza del processore dell'analizzatore sintattico di moduli da utilizzare in Document AI Platform per questo tutorial.

  1. Nella console, vai a Document AI Platform Overview
  2. Fai clic su Crea processore e seleziona Analizzatore moduliProcessori
  3. Specifica un nome del processore e seleziona la tua regione dall'elenco.
  4. Fai clic su Crea per creare il tuo processore
  5. Copia il tuo ID processore. Lo dovrai utilizzare nel tuo codice in un secondo momento.

Testa il processore nella console Cloud

Puoi testare il tuo processore nella console caricando un documento. Fai clic su Carica documento e seleziona un modulo da analizzare. Puoi scaricare e utilizzare questo modulo di esempio se non ne hai uno disponibile.

Modulo sanitario

L'output dovrebbe avere questo aspetto: Modulo analizzato

4. Scarica il modulo di esempio

Abbiamo un documento di esempio che contiene un semplice modulo di assunzione di un medico.

Puoi scaricare il PDF utilizzando il seguente link. Quindi caricalo sull'istanza di Cloud Shell.

In alternativa, puoi scaricarlo dal nostro bucket pubblico di Google Cloud Storage utilizzando gsutil.

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

Verifica che il file sia stato scaricato su Cloud Shell utilizzando il comando seguente:

ls -ltr intake-form.pdf

5. Estrazione di coppie chiave/valore dei moduli

In questo passaggio utilizzerai l'API di elaborazione online per chiamare il processore dell'analizzatore sintattico di moduli che hai creato in precedenza. Quindi, estrarrai le coppie chiave-valore trovate nel documento.

L'elaborazione online consente di inviare un singolo documento e attendere la risposta. Puoi utilizzare l'elaborazione batch anche se vuoi inviare più file o se le dimensioni del file superano il numero massimo di pagine per l'elaborazione online. Puoi rivedere come eseguire questa operazione nel Codelab OCR.

Il codice per effettuare una richiesta di processo è identico per ogni tipo di processore, a parte l'ID processore.

L'oggetto risposta Document contiene un elenco di pagine del documento di input.

Ogni oggetto page contiene un elenco di campi del modulo e le relative posizioni nel testo.

Il seguente codice esegue l'iterazione in ogni pagina ed estrae ogni chiave, valore e punteggio di confidenza. Si tratta di dati strutturati che possono essere archiviati più facilmente nei database o utilizzati in altre applicazioni.

Crea un file denominato form_parser.py e utilizza il codice riportato di seguito.

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)

Esegui ora il codice e dovresti vedere il testo estratto e stampato nella console.

Se utilizzi il nostro documento di esempio, dovresti visualizzare il seguente output:

$ 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. Analizza tabelle

L'analizzatore sintattico di moduli è anche in grado di estrarre i dati dalle tabelle all'interno dei documenti. In questo passaggio scaricheremo un nuovo documento di esempio ed estrarremo i dati dalla tabella. Poiché stiamo caricando i dati in Pandas, questi dati possono essere restituiti in un file CSV e in molti altri formati con una singola chiamata al metodo.

Scarica il modulo di esempio con tabelle

Abbiamo un documento di esempio che contiene un modulo di esempio e una tabella.

Puoi scaricare il PDF utilizzando il seguente link. Quindi caricalo sull'istanza di Cloud Shell.

In alternativa, puoi scaricarlo dal nostro bucket pubblico di Google Cloud Storage utilizzando gsutil.

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

Verifica che il file sia stato scaricato su Cloud Shell utilizzando il comando seguente:

ls -ltr form_with_tables.pdf

Estrai i dati della tabella

La richiesta di elaborazione dei dati della tabella è esattamente la stessa dell'estrazione di coppie chiave-valore. La differenza è da quali campi estraiamo i dati nella risposta. I dati della tabella vengono archiviati nel campo pages[].tables[].

Questo esempio estrae le informazioni dalle righe di intestazione della tabella e da quelle del corpo di ogni tabella e pagina, quindi stampa la tabella e la salva come file CSV.

Crea un file denominato table_parsing.py e utilizza il codice riportato di seguito.

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)

Esegui ora il codice e dovresti vedere il testo estratto e stampato nella console.

Se utilizzi il nostro documento di esempio, dovresti visualizzare il seguente output:

$ 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

Dovresti anche avere due nuovi file CSV nella directory da cui esegui il codice.

$ ls
form_with_tables_pg1_tb0.csv form_with_tables_pg1_tb1.csv table_parsing.py

7. Complimenti

Complimenti, hai utilizzato correttamente l'API Document AI per estrarre i dati da un modulo scritto a mano. Ti invitiamo a provare altri documenti del modulo.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial:

  • Nella console Cloud, vai alla pagina Gestisci risorse.
  • Nell'elenco dei progetti, seleziona il progetto e fai clic su Elimina.
  • Nella finestra di dialogo, digita l'ID progetto e fai clic su Chiudi per eliminare il progetto.

Scopri di più

Continua a imparare su Document AI con questi codelab di follow-up.

Risorse

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.