

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Procesamiento de documentos con operaciones asíncronas
<a name="async"></a>

Amazon Textract Texact puede detectar y analizar texto en documentos de varias páginas en formato PDF o TIFF. Esto incluye facturas y recibos. El procesamiento de documentos de varias páginas es asíncrona. El procesamiento asíncrono de documentos resulta útil para procesar documentos grandes de varias páginas. Por ejemplo, un archivo PDF con más de 1.000 páginas tarda un tiempo en procesarse. El procesamiento del archivo PDF de forma asíncrona permite que la aplicación complete otras tareas mientras espera a que se complete el proceso. 

En esta sección se explica cómo puede utilizar Amazon Textract para detectar y analizar texto de forma asíncrona en un documento de varias páginas o de una sola página. Los documentos de varias páginas deben estar en formato PDF o TIFF. Los documentos de una sola página procesados con operaciones asíncronas pueden estar en formato JPEG, PNG, TIFF o PDF.

Puede utilizar operaciones asíncronas de Amazon Textract Texact para lo siguiente:
+ Detección de texto: puede detectar líneas y palabras en un documento de varias páginas. Las operaciones asíncronas son[StartDocumentTextDetection](API_StartDocumentTextDetection.md)y[GetDocumentTextDetection](API_GetDocumentTextDetection.md). Para obtener más información, consulte [Detección de texto](how-it-works-detecting.md).
+ Análisis de texto: puede identificar las relaciones entre el texto detectado en un documento de varias páginas. Las operaciones asíncronas son[StartDocumentAnalysis](API_StartDocumentAnalysis.md)y[GetDocumentAnalysis](API_GetDocumentAnalysis.md). Para obtener más información, consulte [Análisis de documentos](how-it-works-analyzing.md).
+ Análisis de gastos: puede identificar las relaciones de datos en facturas y recibos de varias páginas. Amazon Textract Texact trata cada factura o página de recepción de un documento de varias páginas como un recibo individual o una factura. No conserva el contexto de una página a otra de un documento de varias páginas. Las operaciones asíncronas son[StartExpenseAnalysis](API_StartExpenseAnalysis.md)y[GetExpenseAnalysis](API_GetExpenseAnalysis.md). Para obtener más información, consulte [Análisis de facturas y recibos](invoices-receipts.md).

**Topics**
+ [Llamar a operaciones asíncronas de Amazon Textract](api-async.md)
+ [Configuración de Amazon Textract Texact para operaciones asíncronas](api-async-roles.md)
+ [Detección o análisis de texto en un documento de varias páginas](async-analyzing-with-sqs.md)
+ [Notificación de resultados de Amazon Textract](async-notification-payload.md)

# Llamar a operaciones asíncronas de Amazon Textract
<a name="api-async"></a>

Amazon Textract Texact proporciona una API asíncrona que puede utilizar para procesar documentos de varias páginas en formato PDF o TIFF. También puede utilizar operaciones asíncronas para procesar documentos de una sola página en formato JPEG, PNG, TIFF o PDF. 

La información de este tema utiliza operaciones de detección de texto para mostrar cómo utilizar las operaciones asíncronas de Amazon Textract Texact. El mismo enfoque funciona con las operaciones de análisis de textos de[StartDocumentAnalysis](API_StartDocumentAnalysis.md)y[GetDocumentAnalysis](API_GetDocumentAnalysis.md). También funciona igual con[StartExpenseAnalysis](API_StartExpenseAnalysis.md)y[GetExpenseAnalysis](API_GetExpenseAnalysis.md). 

Para ver un ejemplo, consulte [Detección o análisis de texto en un documento de varias páginas](async-analyzing-with-sqs.md).

Amazon Textract procesa de forma asíncrona un documento almacenado en un bucket de Amazon S3. Empiezas a procesar llamando a un`Start`operación, tales como[StartDocumentTextDetection](API_StartDocumentTextDetection.md). El estado de realización de la solicitud se publica en un tema de Amazon Simple Notification Service (Amazon SNS). Para obtener el estado de realización del tema de Amazon SNS, puede utilizar una cola de Amazon Simple Queue Service (Amazon SQS) o unaAWS Lambdafunción. Una vez que disponga del estado de realización, llame a una operación `Get`, como [GetDocumentTextDetection](API_GetDocumentTextDetection.md), para obtener los resultados de la solicitud. 

Los resultados de las llamadas asíncronas se cifran y almacenan durante 7 días en un bucket propiedad de Amazon Textract Texact de forma predeterminada, a menos que especifique un bucket de Amazon S3 mediante una operación`OutputConfig`argumento.

En la tabla siguiente se muestran las operaciones Start y Get correspondientes para los distintos tipos de procesamiento asíncrono admitidos por Amazon Textract:


**Iniciar/obtener operaciones de API para operaciones asíncronas de Amazon Textract**  

| Tipo de procesamiento | API de inicio | Obtenga la API | 
| --- | --- | --- | 
| Detección de texto | StartDocumentTextDetection | GetDocumentTextDetection | 
| Análisis de texto | StartDocumentAnalysis | GetDocumentAnalysis | 
| Análisis de gastos | Iniciar análisis de gastos | Obtener análisis de gastos | 

Para un ejemplo que utilizaAWS Lambdafunciones, consulte[Procesamiento de documentos a gran escala con Amazon Textract](https://github.com/aws-samples/amazon-textract-serverless-large-scale-document-processing).

En el siguiente diagrama se muestra el proceso para detectar el texto de un documento en una imagen de documento almacenada en un bucket de Amazon S3. En el diagrama, una cola de Amazon SQS obtiene el estado de realización a partir del tema de Amazon SNS. 

![\[alt text not found\]](http://docs.aws.amazon.com/es_es/textract/latest/dg/images/asynchronous.png)


El proceso que muestra el diagrama anterior es el mismo para analizar texto y facturas/recibos. Empiezas a analizar texto llamando[StartDocumentAnalysis](API_StartDocumentAnalysis.md)y comienza a analizar facturas/recibos llamando[StartExpenseAnalysis](API_StartExpenseAnalysis.md)Obtienes los resultados llamando[GetDocumentAnalysis](API_GetDocumentAnalysis.md)o[GetExpenseAnalysis](API_GetExpenseAnalysis.md)respectivamente.

## Iniciar la detección de texto
<a name="api-async-start"></a>

Para iniciar una solicitud de detección de texto de Amazon Textract, llame a[StartDocumentTextDetection](API_StartDocumentTextDetection.md). El siguiente es un ejemplo de una solicitud JSON que ha transferido `StartDocumentTextDetection`.

```
{
    "DocumentLocation": {
        "S3Object": {
            "Bucket": "bucket",
            "Name": "image.pdf"
        }
    },
    "ClientRequestToken": "DocumentDetectionToken",
    "NotificationChannel": {
        "SNSTopicArn": "arn:aws:sns:us-east-1:nnnnnnnnnn:topic",
        "RoleArn": "arn:aws:iam::nnnnnnnnnn:role/roleTopic"
    },
    "JobTag": "Receipt"
}
```

El parámetro de entrada`DocumentLocation`proporciona el nombre de archivo de documento y el bucket de Amazon S3 desde el que recuperarlo.`NotificationChannel`contiene el nombre de recurso de Amazon (ARN) del tema de Amazon SNS que Amazon Textract notifica cuando finaliza la solicitud de detección de texto. El tema de Amazon SNS debe estar en la misma región de AWS que el punto de enlace Amazon Textract Texact al que está llamando.`NotificationChannel`también contiene el ARN de un rol que permite a Amazon Textract Texact publicar en el tema de Amazon SNS. Puede conceder permisos de Amazon Textract Texact a sus temas de Amazon SNS creando un rol de servicio de IAM. Para obtener más información, consulte [Configuración de Amazon Textract Texact para operaciones asíncronas](api-async-roles.md).

También puede especificar un parámetro de entrada opcional,`JobTag`, que le permite identificar el trabajo o los grupos de trabajos en el estado de realización que se ha publicado en el tema de Amazon SNS. Por ejemplo, puede utilizar`JobTag`para identificar el tipo de documento que se está procesando, como un formulario fiscal o un recibo.

Para evitar la duplicación accidental de trabajos de análisis, tiene la opción de proporcionar un token idempotente, `ClientRequestToken`. Si proporciona un valor para`ClientRequestToken`, el`Start`La operación devuelve lo mismo`JobId`para varias llamadas idénticas al`Start`operación, tales como`StartDocumentTextDetection`. Un token `ClientRequestToken` tiene una vida útil de 7 días. Después de 7 días, puede volver a utilizarla. Si reutiliza el token durante el ciclo de vida del token, sucede lo siguiente: 
+ Si reutiliza el token con la misma operación `Start` y los mismos parámetros de entrada, se devuelve el mismo `JobId`. El trabajo no se vuelve a realizar de nuevo y Amazon Textract no envía un estado de realización al tema de Amazon SNS registrado.
+ Si vuelve a utilizar el token con la misma operación `Start` y un cambio de parámetro de entrada menor, obtendrá una excepción `idempotentparametermismatchexception` (código de estado HTTP: 400).
+ Si reutiliza el token con otra operación `Start` distinta, la operación se realiza correctamente.

Otro parámetro opcional disponible es`OutputConfig`, que le permite ajustar dónde se colocará la salida. De forma predeterminada, Amazon Textract Texact almacenará los resultados internamente y solo se puede acceder a ellos mediante las operaciones de Get API. con`OutputConfig`habilitado, puede establecer el nombre del depósito al que se enviará la salida y el prefijo de archivo de los resultados, donde puede descargar los resultados. También puede configurar la`KMSKeyID`parámetro a una clave administrada por el cliente para cifrar la salida. Sin este conjunto de parámetros, Amazon Textract Texact cifrará el lado del servidor mediante elClave administrada de AWSpara Amazon S3

**nota**  
Antes de utilizar este parámetro, asegúrese de tener el permiso PutObject para el bucket de salida. Además, asegúrese de tener los permisos Descifrar, ReEncrypt, GenerateDataKey y DescribeKey para elAWS KMSclave si decides usarla.

La respuesta a la operación `StartDocumentTextDetection` es un identificador de trabajo (`JobId`). Usar`JobId`para realizar un seguimiento de las solicitudes y obtener los resultados de análisis después de que Amazon Textract haya publicado el estado de realización en el tema de Amazon SNS. A continuación se muestra un ejemplo:

```
{"JobId":"270c1cc5e1d0ea2fbc59d97cb69a72a5495da75851976b14a1784ca90fc180e3"}
```

Si empiezas demasiados trabajos simultáneamente, llama a`StartDocumentTextDetection`RAISE UN`LimitExceededException`excepción (código de estado HTTP: 400) hasta que el número de trabajos ejecutados simultáneamente se encuentre por debajo del límite de servicio de Amazon Textract Texact. 

Si descubre que las excepciones LimitExceededException se producen con picos de actividad, considere la posibilidad de usar una cola de Amazon SQS para administrar las solicitudes entrantes. ContactoAWSSupport técnico si descubre que el número medio de solicitudes simultáneas no se puede administrar con una cola de Amazon SQS y sigue recibiendo`LimitExceededException`excepciones. 

## Obtención del estado de realización de una solicitud de Amazon Textract Analysis
<a name="api-async-get-status"></a>

Amazon Textract envía una notificación a la realización de análisis al tema de Amazon SNS registrado. La notificación incluye el identificador de trabajo y el estado de realización de la operación en una cadena de JSON. Una solicitud de detección de texto correcta tiene un`SUCCEEDED`estado. Por ejemplo, el siguiente resultado muestra el procesamiento correcto de un trabajo de detección de texto.

```
{
    "JobId": "642492aea78a86a40665555dc375ee97bc963f342b29cd05030f19bd8fd1bc5f",
    "Status": "SUCCEEDED",
    "API": "StartDocumentTextDetection",
    "JobTag": "Receipt",
    "Timestamp": 1543599965969,
    "DocumentLocation": {
        "S3ObjectName": "document",
        "S3Bucket": "bucket"
    }
}
```

Para obtener más información, consulte [Notificación de resultados de Amazon Textract](async-notification-payload.md).

Para obtener la información de estado que Amazon Textract ha publicado en el tema de Amazon SNS, utilice una de las siguientes opciones:
+ **AWS Lambda**— Puede suscribirse a unAWS Lambdaque escribe en un tema de Amazon SNS. Se llama a la función cuando Amazon Textract notifica al tema de Amazon SNS que la solicitud se ha completado. Utilice una función Lambda si desea que el código del servidor procese los resultados de una solicitud de detección de texto. Por ejemplo, es posible que desee utilizar el código del servidor para anotar la imagen o crear un informe sobre el texto detectado antes de devolver la información a una aplicación cliente.
+ **Amazon SQS**— Puede suscribir una cola de Amazon SQS a un tema de Amazon SNS. A continuación, sondee la cola de Amazon SQS para recuperar el estado de realización publicado por Amazon Textract cuando se completa una solicitud de detección de texto. Para obtener más información, consulte [Detección o análisis de texto en un documento de varias páginas](async-analyzing-with-sqs.md). Utilice una cola de Amazon SQS si desea llamar a operaciones de Amazon Textract Texact solo desde una aplicación cliente. 

**importante**  
No le recomendamos obtener el estado de realización de solicitud llamando repetidamente a Amazon Textract`Get`. Esto se debe a que Amazon Textract Texact limita el`Get`si se realizan demasiadas solicitudes. Si está procesando varios documentos al mismo tiempo, es más sencillo y más eficaz supervisar una cola de SQS para la notificación de realización que sondear Amazon Textract detectar el estado de cada trabajo individualmente.

## Obtener resultados de detección de texto de Amazon Textract
<a name="api-async-get"></a>

Para obtener los resultados de una solicitud de detección de texto, en primer lugar, asegúrese de que el estado de realización que se ha recuperado del tema de Amazon SNS es`SUCCEEDED`. A continuación, llame a `GetDocumentTextDetection`, que transfiere el valor `JobId` que se devuelve desde `StartDocumentTextDetection`. El JSON de la solicitud es similar al siguiente ejemplo:

```
{
    "JobId": "270c1cc5e1d0ea2fbc59d97cb69a72a5495da75851976b14a1784ca90fc180e3",
    "MaxResults": 10,
    "SortBy": "TIMESTAMP"
}
```

`JobId`es el identificador de la operación de detección de texto. Como la detección de texto puede generar grandes cantidades de datos, utilice`MaxResults`para especificar el número máximo de resultados que se devuelven en un solo`Get`. El valor predeterminado de`MaxResults`es 1000. Si especifica un valor superior a 1 000, solo se devuelven 1 000 resultados. Si la operación no devuelve todos los resultados, se devuelve un token de paginación para la página siguiente. Para obtener la siguiente página de resultados, especifique el token en el`NextToken`parámetro. 

**nota**  
Amazon Textract Texact conserva los resultados de operaciones asíncronas durante siete días. No puede recuperar los resultados transcurrido este plazo.

La`GetDocumentTextDetection`JSON de respuesta de operación es similar al siguiente. El número total de páginas detectadas se devuelve en`DocumentMetadata`. El texto detectado se devuelve en el`Blocks`matriz. Para obtener información sobre`Block`objetos, consulte[Objetos de respuesta de detección de texto y análisis de documentos](how-it-works-document-layout.md).

```
{
    "DocumentMetadata": {
        "Pages": 1
    },
    "JobStatus": "SUCCEEDED",
    "Blocks": [
        {
            "BlockType": "PAGE",
            "Geometry": {
                "BoundingBox": {
                    "Width": 1.0,
                    "Height": 1.0,
                    "Left": 0.0,
                    "Top": 0.0
                },
                "Polygon": [
                    {
                        "X": 0.0,
                        "Y": 0.0
                    },
                    {
                        "X": 1.0,
                        "Y": 0.0
                    },
                    {
                        "X": 1.0,
                        "Y": 1.0
                    },
                    {
                        "X": 0.0,
                        "Y": 1.0
                    }
                ]
            },
            "Id": "64533157-c47e-401a-930e-7ca1bb3ac3fa",
            "Relationships": [
                {
                    "Type": "CHILD",
                    "Ids": [
                        "4297834d-dcb1-413b-8908-3b96866ebbb5",
                        "1d85ba24-2877-4d09-b8b2-393833d769e9",
                        "193e9c47-fd87-475a-ba09-3fda210d8784",
                        "bd8aeb62-961b-4b47-b78a-e4ed9eeecd0f"
                    ]
                }
            ],
            "Page": 1
        },
        {
            "BlockType": "LINE",
            "Confidence": 53.301639556884766,
            "Text": "ellooworio",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.9999999403953552,
                    "Height": 0.5365243554115295,
                    "Left": 0.0,
                    "Top": 0.46347561478614807
                },
                "Polygon": [
                    {
                        "X": 0.0,
                        "Y": 0.46347561478614807
                    },
                    {
                        "X": 0.9999999403953552,
                        "Y": 0.46347561478614807
                    },
                    {
                        "X": 0.9999999403953552,
                        "Y": 1.0
                    },
                    {
                        "X": 0.0,
                        "Y": 1.0
                    }
                ]
            },
            "Id": "4297834d-dcb1-413b-8908-3b96866ebbb5",
            "Relationships": [
                {
                    "Type": "CHILD",
                    "Ids": [
                        "170c3eb9-5155-4bec-8c44-173bba537e70"
                    ]
                }
            ],
            "Page": 1
        },
        {
            "BlockType": "LINE",
            "Confidence": 89.15632629394531,
            "Text": "He llo,",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.33642634749412537,
                    "Height": 0.49159330129623413,
                    "Left": 0.13885067403316498,
                    "Top": 0.17169663310050964
                },
                "Polygon": [
                    {
                        "X": 0.13885067403316498,
                        "Y": 0.17169663310050964
                    },
                    {
                        "X": 0.47527703642845154,
                        "Y": 0.17169663310050964
                    },
                    {
                        "X": 0.47527703642845154,
                        "Y": 0.6632899641990662
                    },
                    {
                        "X": 0.13885067403316498,
                        "Y": 0.6632899641990662
                    }
                ]
            },
            "Id": "1d85ba24-2877-4d09-b8b2-393833d769e9",
            "Relationships": [
                {
                    "Type": "CHILD",
                    "Ids": [
                        "516ae823-3bab-4f9a-9d74-ad7150d128ab",
                        "6bcf4ea8-bbe8-4686-91be-b98dd63bc6a6"
                    ]
                }
            ],
            "Page": 1
        },
        {
            "BlockType": "LINE",
            "Confidence": 82.44834899902344,
            "Text": "worlo",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.33182239532470703,
                    "Height": 0.3766750991344452,
                    "Left": 0.5091826915740967,
                    "Top": 0.23131252825260162
                },
                "Polygon": [
                    {
                        "X": 0.5091826915740967,
                        "Y": 0.23131252825260162
                    },
                    {
                        "X": 0.8410050868988037,
                        "Y": 0.23131252825260162
                    },
                    {
                        "X": 0.8410050868988037,
                        "Y": 0.607987642288208
                    },
                    {
                        "X": 0.5091826915740967,
                        "Y": 0.607987642288208
                    }
                ]
            },
            "Id": "193e9c47-fd87-475a-ba09-3fda210d8784",
            "Relationships": [
                {
                    "Type": "CHILD",
                    "Ids": [
                        "ed135c3b-35dd-4085-8f00-26aedab0125f"
                    ]
                }
            ],
            "Page": 1
        },
        {
            "BlockType": "LINE",
            "Confidence": 88.50325775146484,
            "Text": "world",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.35004907846450806,
                    "Height": 0.19635874032974243,
                    "Left": 0.527581512928009,
                    "Top": 0.30100569128990173
                },
                "Polygon": [
                    {
                        "X": 0.527581512928009,
                        "Y": 0.30100569128990173
                    },
                    {
                        "X": 0.8776305913925171,
                        "Y": 0.30100569128990173
                    },
                    {
                        "X": 0.8776305913925171,
                        "Y": 0.49736443161964417
                    },
                    {
                        "X": 0.527581512928009,
                        "Y": 0.49736443161964417
                    }
                ]
            },
            "Id": "bd8aeb62-961b-4b47-b78a-e4ed9eeecd0f",
            "Relationships": [
                {
                    "Type": "CHILD",
                    "Ids": [
                        "9e28834d-798e-4a62-8862-a837dfd895a6"
                    ]
                }
            ],
            "Page": 1
        },
        {
            "BlockType": "WORD",
            "Confidence": 53.301639556884766,
            "Text": "ellooworio",
            "Geometry": {
                "BoundingBox": {
                    "Width": 1.0,
                    "Height": 0.5365243554115295,
                    "Left": 0.0,
                    "Top": 0.46347561478614807
                },
                "Polygon": [
                    {
                        "X": 0.0,
                        "Y": 0.46347561478614807
                    },
                    {
                        "X": 1.0,
                        "Y": 0.46347561478614807
                    },
                    {
                        "X": 1.0,
                        "Y": 1.0
                    },
                    {
                        "X": 0.0,
                        "Y": 1.0
                    }
                ]
            },
            "Id": "170c3eb9-5155-4bec-8c44-173bba537e70",
            "Page": 1
        },
        {
            "BlockType": "WORD",
            "Confidence": 88.46246337890625,
            "Text": "He",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.15350718796253204,
                    "Height": 0.29955607652664185,
                    "Left": 0.13885067403316498,
                    "Top": 0.21856294572353363
                },
                "Polygon": [
                    {
                        "X": 0.13885067403316498,
                        "Y": 0.21856294572353363
                    },
                    {
                        "X": 0.292357861995697,
                        "Y": 0.21856294572353363
                    },
                    {
                        "X": 0.292357861995697,
                        "Y": 0.5181190371513367
                    },
                    {
                        "X": 0.13885067403316498,
                        "Y": 0.5181190371513367
                    }
                ]
            },
            "Id": "516ae823-3bab-4f9a-9d74-ad7150d128ab",
            "Page": 1
        },
        {
            "BlockType": "WORD",
            "Confidence": 89.8501968383789,
            "Text": "llo,",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.17724157869815826,
                    "Height": 0.49159327149391174,
                    "Left": 0.2980354428291321,
                    "Top": 0.17169663310050964
                },
                "Polygon": [
                    {
                        "X": 0.2980354428291321,
                        "Y": 0.17169663310050964
                    },
                    {
                        "X": 0.47527703642845154,
                        "Y": 0.17169663310050964
                    },
                    {
                        "X": 0.47527703642845154,
                        "Y": 0.6632899045944214
                    },
                    {
                        "X": 0.2980354428291321,
                        "Y": 0.6632899045944214
                    }
                ]
            },
            "Id": "6bcf4ea8-bbe8-4686-91be-b98dd63bc6a6",
            "Page": 1
        },
        {
            "BlockType": "WORD",
            "Confidence": 82.44834899902344,
            "Text": "worlo",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.33182239532470703,
                    "Height": 0.3766750991344452,
                    "Left": 0.5091826915740967,
                    "Top": 0.23131252825260162
                },
                "Polygon": [
                    {
                        "X": 0.5091826915740967,
                        "Y": 0.23131252825260162
                    },
                    {
                        "X": 0.8410050868988037,
                        "Y": 0.23131252825260162
                    },
                    {
                        "X": 0.8410050868988037,
                        "Y": 0.607987642288208
                    },
                    {
                        "X": 0.5091826915740967,
                        "Y": 0.607987642288208
                    }
                ]
            },
            "Id": "ed135c3b-35dd-4085-8f00-26aedab0125f",
            "Page": 1
        },
        {
            "BlockType": "WORD",
            "Confidence": 88.50325775146484,
            "Text": "world",
            "Geometry": {
                "BoundingBox": {
                    "Width": 0.35004907846450806,
                    "Height": 0.19635874032974243,
                    "Left": 0.527581512928009,
                    "Top": 0.30100569128990173
                },
                "Polygon": [
                    {
                        "X": 0.527581512928009,
                        "Y": 0.30100569128990173
                    },
                    {
                        "X": 0.8776305913925171,
                        "Y": 0.30100569128990173
                    },
                    {
                        "X": 0.8776305913925171,
                        "Y": 0.49736443161964417
                    },
                    {
                        "X": 0.527581512928009,
                        "Y": 0.49736443161964417
                    }
                ]
            },
            "Id": "9e28834d-798e-4a62-8862-a837dfd895a6",
            "Page": 1
        }
    ]
}
```

# Configuración de Amazon Textract Texact para operaciones asíncronas
<a name="api-async-roles"></a>

En los siguientes procedimientos se muestra cómo configurar Amazon Textract para que lo utilice con un tema de Amazon Simple Notification Service (Amazon SNS) y una cola de Amazon Simple Queue Service (Amazon SQS).

**nota**  
Si está utilizando estas instrucciones para configurar el[Detección o análisis de texto en un documento de varias páginas](async-analyzing-with-sqs.md)ejemplo, no es necesario realizar los pasos 3 a 6. El ejemplo incluye código que permite crear y configurar el tema de Amazon SNS y la cola de Amazon SQS.

**Para configurar Amazon Textract**

1. Configurar unAWScuenta para acceder a Amazon Textract. Para obtener más información, consulte [Paso 1: Configuración de una cuenta de AWS y creación de un usuario de IAM](setting-up.md).

   Asegúrese de que el usuario tiene al menos los permisos siguientes:
   + AmazonTextractFullAccess
   + AmazonS3ReadOnlyAccess
   + AmazonSNSFullAccess
   + AmazonSQSFullAccess

1. Instale y configure el SDK de AWS necesario. Para obtener más información, consulte [Paso 2: Configurar laAWS CLIyAWSSDK de](setup-awscli-sdk.md). 

1. [Cree un tema de Amazon SNS.](https://docs.aws.amazon.com/sns/latest/dg/sns-tutorial-create-topic.html). Anexa el nombre del tema con*Extracto de Amazon*. Anote el nombre de recurso de Amazon (ARN) del tema. Asegúrese de que el tema de está en la misma región de que elAWSpunto de enlace que está utilizando con su cuenta de AWS.

1. [Cree una cola estándar de Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)mediante el uso de la[Consola de Amazon SQS](https://console.aws.amazon.com/sqs/). Anote el ARN de la cola.

1. [Suscriba la cola al tema](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-subscribe-queue-sns-topic.html) que creó en el paso 3.

1. [Conceder permiso al tema de Amazon SNS para enviar mensajes a la cola de Amazon SQS](https://docs.aws.amazon.com/sns/latest/dg/subscribe-sqs-queue-to-sns-topic.html).

1. Cree una función de servicio de IAM para dar a Amazon Textract Texact acceso a sus temas de Amazon SNS. Anote el nombre de recurso de Amazon (ARN) del rol de servicio. Para obtener más información, consulte [Conceder acceso a Amazon Textract a su tema de Amazon SNS](#api-async-roles-all-topics).

1. [Añada la siguiente política insertada](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#embed-inline-policy-console)al usuario de IAM que ha creado en el paso 1. 

   ```
   {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Sid": "MySid",
               "Effect": "Allow",
               "Action": "iam:PassRole",
               "Resource": "Service role ARN from step 7"
           }
       ]
   }
   ```

   Asigne un nombre a la política insertada.

1. Ahora puede ejecutar los ejemplos de[Detección o análisis de texto en un documento de varias páginas](async-analyzing-with-sqs.md).

## Conceder acceso a Amazon Textract a su tema de Amazon SNS
<a name="api-async-roles-all-topics"></a>

Amazon Textract Texact necesita permiso para enviar un mensaje al tema de Amazon SNS cuando se haya completado una operación asíncrona. Utilice un rol de servicio de IAM para dar a Amazon Textract Texact acceso al tema de Amazon SNS. 

 Al crear el tema de Amazon SNS, debe añadir el nombre del tema con**AmazonTextract**—por ejemplo,**AmazonTextractMyTopicName**. 

1. Inicie sesión en la consola de IAM ([https://console.aws.amazon.com/iam](https://console.aws.amazon.com/iam)).

1. Seleccione **Roles** en el panel de navegación.

1. Elija **Create role**.

1. En **Select type of trusted entity (Seleccionar tipo de entidad de confianza)**, elija **AWS service (Servicio de AWS)**. 

1. Para**Elija el servicio que utilizará este rol**, elige**Textract**.

1. Seleccione **Next (Siguiente): Permisos**.

1. Verifique que la**AmazonTextractServiceRole**se ha incluido en la lista de políticas adjuntas. Para mostrar la política en la lista, escriba parte del nombre de la política en el**Políticas de filtrado**.

1. Seleccione **Next (Siguiente): Tags (Etiquetas)**.

1. No es necesario añadir etiquetas, así que elija**Siguiente: Consulte**.

1. En la sección **Review (Revisar)**, en **Role Name (Nombre de rol)**, escriba un nombre para el rol (por ejemplo, `TextractRole`). En**Descripción del rol**, actualice la descripción de la función y, a continuación, elija**Crear rol**.

1. Elija el rol nuevo para abrir la página de detalles del rol.

1. En **Summary (Resumen)**, copie el valor de **Role ARN (ARN del rol)** y guárdelo.

1. Seleccione **Trust Relationships**.

1. Elegir**Modificar relación de confianza**y garantizar que la política de fideicomiso tenga el siguiente aspecto.

   ```
   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "textract.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

1. Elija **Update Trust Policy** (Actualizar política de confianza).

# Detección o análisis de texto en un documento de varias páginas
<a name="async-analyzing-with-sqs"></a>

Este procedimiento muestra cómo detectar o analizar texto en un documento de varias páginas mediante operaciones de detección de Amazon Textract Texact, un documento almacenado en un depósito de Amazon S3, un tema de Amazon SNS y una cola de Amazon SQS. El procesamiento de documentos de varias páginas es asíncrona. Para obtener más información, consulte [Llamar a operaciones asíncronas de Amazon Textract](api-async.md).

Puede elegir el tipo de procesamiento que desea que realice el código: detección de texto, análisis de texto o análisis de gastos. 

Los resultados del procesamiento se devuelven en una matriz de[Block](API_Block.md)objetos que varían según el tipo de procesamiento que utilice.

 Para detectar texto o analizar documentos de varias páginas, haga lo siguiente:

1. Cree el tema de Amazon SNS y la cola de Amazon SQS.

1. Suscriba la cola de al tema de.

1. Conceda permiso al tema de para enviar mensajes a la cola de.

1. Comience a procesar el documento. Utilice la operación adecuada para el tipo de análisis elegido:
   + [StartDocumentTextDetection](API_StartDocumentTextDetection.md)para tareas de detección de texto.
   + [StartDocumentAnalysis](API_StartDocumentAnalysis.md)para tareas de análisis de texto.
   + [StartExpenseAnalysis](API_StartExpenseAnalysis.md)para tareas de análisis de gastos.

1. Obtenga el estado de realización a partir de la cola de Amazon SQS. El código de ejemplo hace un seguimiento del identificador del trabajo (`JobId`) devuelto por el`Start`. Solo obtiene los resultados de identificadores de trabajo coincidentes que se leen desde el estado de realización. Esto es importante si otras aplicaciones están utilizando la misma cola de y tema de. Para simplificar, en el ejemplo se eliminan los trabajos que no coinciden. Plantéese añadir los trabajos eliminados a una cola de mensajes erróneos de Amazon SQS para examinarlos posteriormente.

1. Obtenga y muestre los resultados del procesamiento llamando a la operación adecuada para el tipo de análisis elegido:
   + [GetDocumentTextDetection](API_GetDocumentTextDetection.md)para tareas de detección de texto.
   + [GetDocumentAnalysis](API_GetDocumentAnalysis.md)para tareas de análisis de texto.
   + [GetExpenseAnalysis](API_GetExpenseAnalysis.md)para tareas de análisis de gastos.

1. Elimine el tema de Amazon SNS y la cola de Amazon SQS.

## Realización de operaciones asíncronas
<a name="async-prerequisites"></a>

El código de ejemplo de este procedimiento se proporciona en Java, Python yAWS CLI. Antes de comenzar, instale el correspondienteAWSSDK. Para obtener más información, consulte [Paso 2: Configurar laAWS CLIyAWSSDK de](setup-awscli-sdk.md). 

**Para detectar o analizar texto en un documento de varias páginas**

1. Configure el acceso de usuario a Amazon Textract y configure el acceso de Amazon Textract Texact a Amazon SNS. Para obtener más información, consulte [Configuración de Amazon Textract Texact para operaciones asíncronas](api-async-roles.md). Para completar este procedimiento, se necesita un archivo de documento de varias páginas en formato PDF. Omita los pasos 3 a 6, ya que el código de ejemplo crea y configura el tema de Amazon SNS y la cola de Amazon SQS. Si es complejotEn el ejemplo de la CLI, no es necesario configurar una cola de SQS. 

1. Cargue un archivo de documento de varias páginas en formato PDF o TIFF a su bucket de Amazon S3. (También se pueden procesar documentos de una sola página en formato JPEG, PNG, TIFF o PDF). 

   Para obtener instrucciones, consulte[Carga de objetos en Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/UploadingObjectsintoAmazonS3.html)en la*Amazon Simple Storage Service*.

1. Utilice lo siguienteAWS SDK para Java, SDK for Python (Boto3) oAWS CLIcódigo para detectar texto o analizar texto en un documento de varias páginas. En el navegador`main`función:
   + Sustituir el valor de`roleArn`con el ARN del rol de IAM que ha guardado en[Conceder acceso a Amazon Textract a su tema de Amazon SNS](api-async-roles.md#api-async-roles-all-topics). 
   + Sustituir los valores de`bucket`y`document`con el nombre del bucket de y el nombre del archivo de documento que especificó en el paso 2. 
   + Sustituya el valor de la`type`parámetro de entrada del`ProcessDocument`función con el tipo de procesamiento que desea realizar. Usar`ProcessType.DETECTION`para detectar texto. Usar`ProcessType.ANALYSIS`para analizar texto. 
   + Para el ejemplo de Python, sustituya el valor de`region_name`con la región en la que opera su cliente.

   Para el registroAWS CLIejemplo, haga lo siguiente:
   + Al llamar[StartDocumentTextDetection](API_StartDocumentTextDetection.md), sustituya el valor de`bucket-name`con el nombre de su bucket de S3 y reemplace`file-name`con el nombre del archivo que especificó en el paso 2. Especifique la región de su depósito reemplazando`region-name`con el nombre de su región. Tenga en cuenta que el ejemplo de la CLI no utiliza SQS. 
   + Al llamar[GetDocumentTextDetection](API_GetDocumentTextDetection.md)replace`job-id-number`con`job-id`devuelto por[StartDocumentTextDetection](API_StartDocumentTextDetection.md). Especifique la región de su depósito reemplazando`region-name`con el nombre de su región.

------
#### [ Java ]

   ```
   package com.amazonaws.samples;
   
   import java.util.Arrays;
   import java.util.HashMap;
   import java.util.List;
   import java.util.Map;
   
   import com.amazonaws.auth.policy.Condition;
   import com.amazonaws.auth.policy.Policy;
   import com.amazonaws.auth.policy.Principal;
   import com.amazonaws.auth.policy.Resource;
   import com.amazonaws.auth.policy.Statement;
   import com.amazonaws.auth.policy.Statement.Effect;
   import com.amazonaws.auth.policy.actions.SQSActions;
   import com.amazonaws.services.sns.AmazonSNS;
   import com.amazonaws.services.sns.AmazonSNSClientBuilder;
   import com.amazonaws.services.sns.model.CreateTopicRequest;
   import com.amazonaws.services.sns.model.CreateTopicResult;
   import com.amazonaws.services.sqs.AmazonSQS;
   import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
   import com.amazonaws.services.sqs.model.CreateQueueRequest;
   import com.amazonaws.services.sqs.model.Message;
   import com.amazonaws.services.sqs.model.QueueAttributeName;
   import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;
   import com.amazonaws.services.textract.AmazonTextract;
   import com.amazonaws.services.textract.AmazonTextractClientBuilder;
   import com.amazonaws.services.textract.model.Block;
   import com.amazonaws.services.textract.model.DocumentLocation;
   import com.amazonaws.services.textract.model.DocumentMetadata;
   import com.amazonaws.services.textract.model.GetDocumentAnalysisRequest;
   import com.amazonaws.services.textract.model.GetDocumentAnalysisResult;
   import com.amazonaws.services.textract.model.GetDocumentTextDetectionRequest;
   import com.amazonaws.services.textract.model.GetDocumentTextDetectionResult;
   import com.amazonaws.services.textract.model.NotificationChannel;
   import com.amazonaws.services.textract.model.Relationship;
   import com.amazonaws.services.textract.model.S3Object;
   import com.amazonaws.services.textract.model.StartDocumentAnalysisRequest;
   import com.amazonaws.services.textract.model.StartDocumentAnalysisResult;
   import com.amazonaws.services.textract.model.StartDocumentTextDetectionRequest;
   import com.amazonaws.services.textract.model.StartDocumentTextDetectionResult;
   import com.fasterxml.jackson.databind.JsonNode;
   import com.fasterxml.jackson.databind.ObjectMapper;;
   public class DocumentProcessor {
   
       private static String sqsQueueName=null;
       private static String snsTopicName=null;
       private static String snsTopicArn = null;
       private static String roleArn= null;
       private static String sqsQueueUrl = null;
       private static String sqsQueueArn = null;
       private static String startJobId = null;
       private static String bucket = null;
       private static String document = null; 
       private static AmazonSQS sqs=null;
       private static AmazonSNS sns=null;
       private static AmazonTextract textract = null;
   
       public enum ProcessType {
           DETECTION,ANALYSIS
       }
   
       public static void main(String[] args) throws Exception {
           
           String document = "document";
           String bucket = "bucket";
           String roleArn="role";
   
           sns = AmazonSNSClientBuilder.defaultClient();
           sqs= AmazonSQSClientBuilder.defaultClient();
           textract=AmazonTextractClientBuilder.defaultClient();
           
           CreateTopicandQueue();
           ProcessDocument(bucket,document,roleArn,ProcessType.DETECTION);
           DeleteTopicandQueue();
           System.out.println("Done!");
           
           
       }
       // Creates an SNS topic and SQS queue. The queue is subscribed to the topic. 
       static void CreateTopicandQueue()
       {
           //create a new SNS topic
           snsTopicName="AmazonTextractTopic" + Long.toString(System.currentTimeMillis());
           CreateTopicRequest createTopicRequest = new CreateTopicRequest(snsTopicName);
           CreateTopicResult createTopicResult = sns.createTopic(createTopicRequest);
           snsTopicArn=createTopicResult.getTopicArn();
           
           //Create a new SQS Queue
           sqsQueueName="AmazonTextractQueue" + Long.toString(System.currentTimeMillis());
           final CreateQueueRequest createQueueRequest = new CreateQueueRequest(sqsQueueName);
           sqsQueueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
           sqsQueueArn = sqs.getQueueAttributes(sqsQueueUrl, Arrays.asList("QueueArn")).getAttributes().get("QueueArn");
           
           //Subscribe SQS queue to SNS topic
           String sqsSubscriptionArn = sns.subscribe(snsTopicArn, "sqs", sqsQueueArn).getSubscriptionArn();
           
           // Authorize queue
             Policy policy = new Policy().withStatements(
                     new Statement(Effect.Allow)
                     .withPrincipals(Principal.AllUsers)
                     .withActions(SQSActions.SendMessage)
                     .withResources(new Resource(sqsQueueArn))
                     .withConditions(new Condition().withType("ArnEquals").withConditionKey("aws:SourceArn").withValues(snsTopicArn))
                     );
                     
   
             Map queueAttributes = new HashMap();
             queueAttributes.put(QueueAttributeName.Policy.toString(), policy.toJson());
             sqs.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueUrl, queueAttributes)); 
             
   
            System.out.println("Topic arn: " + snsTopicArn);
            System.out.println("Queue arn: " + sqsQueueArn);
            System.out.println("Queue url: " + sqsQueueUrl);
            System.out.println("Queue sub arn: " + sqsSubscriptionArn );
        }
       static void DeleteTopicandQueue()
       {
           if (sqs !=null) {
               sqs.deleteQueue(sqsQueueUrl);
               System.out.println("SQS queue deleted");
           }
           
           if (sns!=null) {
               sns.deleteTopic(snsTopicArn);
               System.out.println("SNS topic deleted");
           }
       }
       
       //Starts the processing of the input document.
       static void ProcessDocument(String inBucket, String inDocument, String inRoleArn, ProcessType type) throws Exception
       {
           bucket=inBucket;
           document=inDocument;
           roleArn=inRoleArn;
   
           switch(type)
           {
               case DETECTION:
                   StartDocumentTextDetection(bucket, document);
                   System.out.println("Processing type: Detection");
                   break;
               case ANALYSIS:
                   StartDocumentAnalysis(bucket,document);
                   System.out.println("Processing type: Analysis");
                   break;
               default:
                   System.out.println("Invalid processing type. Choose Detection or Analysis");
                   throw new Exception("Invalid processing type");
              
           }
   
           System.out.println("Waiting for job: " + startJobId);
           //Poll queue for messages
           List<Message> messages=null;
           int dotLine=0;
           boolean jobFound=false;
   
           //loop until the job status is published. Ignore other messages in queue.
           do{
               messages = sqs.receiveMessage(sqsQueueUrl).getMessages();
               if (dotLine++<40){
                   System.out.print(".");
               }else{
                   System.out.println();
                   dotLine=0;
               }
   
               if (!messages.isEmpty()) {
                   //Loop through messages received.
                   for (Message message: messages) {
                       String notification = message.getBody();
   
                       // Get status and job id from notification.
                       ObjectMapper mapper = new ObjectMapper();
                       JsonNode jsonMessageTree = mapper.readTree(notification);
                       JsonNode messageBodyText = jsonMessageTree.get("Message");
                       ObjectMapper operationResultMapper = new ObjectMapper();
                       JsonNode jsonResultTree = operationResultMapper.readTree(messageBodyText.textValue());
                       JsonNode operationJobId = jsonResultTree.get("JobId");
                       JsonNode operationStatus = jsonResultTree.get("Status");
                       System.out.println("Job found was " + operationJobId);
                       // Found job. Get the results and display.
                       if(operationJobId.asText().equals(startJobId)){
                           jobFound=true;
                           System.out.println("Job id: " + operationJobId );
                           System.out.println("Status : " + operationStatus.toString());
                           if (operationStatus.asText().equals("SUCCEEDED")){
                               switch(type)
                               {
                                   case DETECTION:
                                       GetDocumentTextDetectionResults();
                                       break;
                                   case ANALYSIS:
                                       GetDocumentAnalysisResults();
                                       break;
                                   default:
                                       System.out.println("Invalid processing type. Choose Detection or Analysis");
                                       throw new Exception("Invalid processing type");
                                  
                               }
                           }
                           else{
                               System.out.println("Document analysis failed");
                           }
   
                           sqs.deleteMessage(sqsQueueUrl,message.getReceiptHandle());
                       }
   
                       else{
                           System.out.println("Job received was not job " +  startJobId);
                           //Delete unknown message. Consider moving message to dead letter queue
                           sqs.deleteMessage(sqsQueueUrl,message.getReceiptHandle());
                       }
                   }
               }
               else {
                   Thread.sleep(5000);
               }
           } while (!jobFound);
   
           System.out.println("Finished processing document");
       }
       
       private static void StartDocumentTextDetection(String bucket, String document) throws Exception{
   
           //Create notification channel 
           NotificationChannel channel= new NotificationChannel()
                   .withSNSTopicArn(snsTopicArn)
                   .withRoleArn(roleArn);
   
           StartDocumentTextDetectionRequest req = new StartDocumentTextDetectionRequest()
                   .withDocumentLocation(new DocumentLocation()
                       .withS3Object(new S3Object()
                           .withBucket(bucket)
                           .withName(document)))
                   .withJobTag("DetectingText")
                   .withNotificationChannel(channel);
   
           StartDocumentTextDetectionResult startDocumentTextDetectionResult = textract.startDocumentTextDetection(req);
           startJobId=startDocumentTextDetectionResult.getJobId();
       }
       
     //Gets the results of processing started by StartDocumentTextDetection
       private static void GetDocumentTextDetectionResults() throws Exception{
           int maxResults=1000;
           String paginationToken=null;
           GetDocumentTextDetectionResult response=null;
           Boolean finished=false;
           
           while (finished==false)
           {
               GetDocumentTextDetectionRequest documentTextDetectionRequest= new GetDocumentTextDetectionRequest()
                       .withJobId(startJobId)
                       .withMaxResults(maxResults)
                       .withNextToken(paginationToken);
               response = textract.getDocumentTextDetection(documentTextDetectionRequest);
               DocumentMetadata documentMetaData=response.getDocumentMetadata();
   
               System.out.println("Pages: " + documentMetaData.getPages().toString());
               
               //Show blocks information
               List<Block> blocks= response.getBlocks();
               for (Block block : blocks) {
                   DisplayBlockInfo(block);
               }
               paginationToken=response.getNextToken();
               if (paginationToken==null)
                   finished=true;
               
           }
           
       }
   
       private static void StartDocumentAnalysis(String bucket, String document) throws Exception{
           //Create notification channel 
           NotificationChannel channel= new NotificationChannel()
                   .withSNSTopicArn(snsTopicArn)
                   .withRoleArn(roleArn);
           
           StartDocumentAnalysisRequest req = new StartDocumentAnalysisRequest()
                   .withFeatureTypes("TABLES","FORMS")
                   .withDocumentLocation(new DocumentLocation()
                       .withS3Object(new S3Object()
                           .withBucket(bucket)
                           .withName(document)))
                   .withJobTag("AnalyzingText")
                   .withNotificationChannel(channel);
   
           StartDocumentAnalysisResult startDocumentAnalysisResult = textract.startDocumentAnalysis(req);
           startJobId=startDocumentAnalysisResult.getJobId();
       }
       //Gets the results of processing started by StartDocumentAnalysis
       private static void GetDocumentAnalysisResults() throws Exception{
   
           int maxResults=1000;
           String paginationToken=null;
           GetDocumentAnalysisResult response=null;
           Boolean finished=false;
           
           //loops until pagination token is null
           while (finished==false)
           {
               GetDocumentAnalysisRequest documentAnalysisRequest= new GetDocumentAnalysisRequest()
                       .withJobId(startJobId)
                       .withMaxResults(maxResults)
                       .withNextToken(paginationToken);
               
               response = textract.getDocumentAnalysis(documentAnalysisRequest);
   
               DocumentMetadata documentMetaData=response.getDocumentMetadata();
   
               System.out.println("Pages: " + documentMetaData.getPages().toString());
   
               //Show blocks, confidence and detection times
               List<Block> blocks= response.getBlocks();
   
               for (Block block : blocks) {
                   DisplayBlockInfo(block);
               }
               paginationToken=response.getNextToken();
               if (paginationToken==null)
                   finished=true;
           }
   
       }
       //Displays Block information for text detection and text analysis
       private static void DisplayBlockInfo(Block block) {
           System.out.println("Block Id : " + block.getId());
           if (block.getText()!=null)
               System.out.println("\tDetected text: " + block.getText());
           System.out.println("\tType: " + block.getBlockType());
           
           if (block.getBlockType().equals("PAGE") !=true) {
               System.out.println("\tConfidence: " + block.getConfidence().toString());
           }
           if(block.getBlockType().equals("CELL"))
           {
               System.out.println("\tCell information:");
               System.out.println("\t\tColumn: " + block.getColumnIndex());
               System.out.println("\t\tRow: " + block.getRowIndex());
               System.out.println("\t\tColumn span: " + block.getColumnSpan());
               System.out.println("\t\tRow span: " + block.getRowSpan());
   
           }
           
           System.out.println("\tRelationships");
           List<Relationship> relationships=block.getRelationships();
           if(relationships!=null) {
               for (Relationship relationship : relationships) {
                   System.out.println("\t\tType: " + relationship.getType());
                   System.out.println("\t\tIDs: " + relationship.getIds().toString());
               }
           } else {
               System.out.println("\t\tNo related Blocks");
           }
   
           System.out.println("\tGeometry");
           System.out.println("\t\tBounding Box: " + block.getGeometry().getBoundingBox().toString());
           System.out.println("\t\tPolygon: " + block.getGeometry().getPolygon().toString());
           
           List<String> entityTypes = block.getEntityTypes();
           
           System.out.println("\tEntity Types");
           if(entityTypes!=null) {
               for (String entityType : entityTypes) {
                   System.out.println("\t\tEntity Type: " + entityType);
               }
           } else {
               System.out.println("\t\tNo entity type");
           }
           
           if(block.getBlockType().equals("SELECTION_ELEMENT")) {
               System.out.print("    Selection element detected: ");
               if (block.getSelectionStatus().equals("SELECTED")){
                   System.out.println("Selected");
               }else {
                   System.out.println(" Not selected");
               }
           }
           if(block.getPage()!=null)
               System.out.println("\tPage: " + block.getPage());            
           System.out.println();
       }
   }
   ```

------
#### [ AWS CLI ]

   EsteAWS CLIinicia la detección asincrónica del texto de un documento especificado. Este método devuelve un objeto`job-id`que se puede utilizar para recuperar los resultados de la detección. 

   ```
   aws textract start-document-text-detection --document-location 
   "{\"S3Object\":{\"Bucket\":\"bucket-name\",\"Name\":\"file-name\"}}" --region region-name
   ```

   EsteAWS CLIdevuelve los resultados de una operación asíncrona de Amazon Textract cuando se proporciona con un`job-id`. 

   ```
   aws textract get-document-text-detection --region region-name --job-id job-id-number
   ```

   Si está accediendo a la CLI en un dispositivo Windows, utilice comillas dobles en lugar de comillas simples y escapa de las comillas dobles internas mediante barra invertida (es decir,\$1) para corregir cualquier error de analizador que pueda surgir. Para un ejemplo, consulte lo siguiente

   ```
   aws textract start-document-text-detection --document-location "{\"S3Object\":{\"Bucket\":\"bucket\",\"Name\":\"document\"}}" --region region-name
   ```

------
#### [ Python ]

   ```
   import boto3
   import json
   import sys
   import time
   
   
   class ProcessType:
       DETECTION = 1
       ANALYSIS = 2
   
   
   class DocumentProcessor:
       jobId = ''
       region_name = ''
   
       roleArn = ''
       bucket = ''
       document = ''
   
       sqsQueueUrl = ''
       snsTopicArn = ''
       processType = ''
   
       def __init__(self, role, bucket, document, region):
           self.roleArn = role
           self.bucket = bucket
           self.document = document
           self.region_name = region
   
           self.textract = boto3.client('textract', region_name=self.region_name)
           self.sqs = boto3.client('sqs')
           self.sns = boto3.client('sns')
   
       def ProcessDocument(self, type):
           jobFound = False
   
           self.processType = type
           validType = False
   
           # Determine which type of processing to perform
           if self.processType == ProcessType.DETECTION:
               response = self.textract.start_document_text_detection(
                   DocumentLocation={'S3Object': {'Bucket': self.bucket, 'Name': self.document}},
                   NotificationChannel={'RoleArn': self.roleArn, 'SNSTopicArn': self.snsTopicArn})
               print('Processing type: Detection')
               validType = True
   
           if self.processType == ProcessType.ANALYSIS:
               response = self.textract.start_document_analysis(
                   DocumentLocation={'S3Object': {'Bucket': self.bucket, 'Name': self.document}},
                   FeatureTypes=["TABLES", "FORMS"],
                   NotificationChannel={'RoleArn': self.roleArn, 'SNSTopicArn': self.snsTopicArn})
               print('Processing type: Analysis')
               validType = True
   
           if validType == False:
               print("Invalid processing type. Choose Detection or Analysis.")
               return
   
           print('Start Job Id: ' + response['JobId'])
           dotLine = 0
           while jobFound == False:
               sqsResponse = self.sqs.receive_message(QueueUrl=self.sqsQueueUrl, MessageAttributeNames=['ALL'],
                                                      MaxNumberOfMessages=10)
   
               if sqsResponse:
   
                   if 'Messages' not in sqsResponse:
                       if dotLine < 40:
                           print('.', end='')
                           dotLine = dotLine + 1
                       else:
                           print()
                           dotLine = 0
                       sys.stdout.flush()
                       time.sleep(5)
                       continue
   
                   for message in sqsResponse['Messages']:
                       notification = json.loads(message['Body'])
                       textMessage = json.loads(notification['Message'])
                       print(textMessage['JobId'])
                       print(textMessage['Status'])
                       if str(textMessage['JobId']) == response['JobId']:
                           print('Matching Job Found:' + textMessage['JobId'])
                           jobFound = True
                           self.GetResults(textMessage['JobId'])
                           self.sqs.delete_message(QueueUrl=self.sqsQueueUrl,
                                                   ReceiptHandle=message['ReceiptHandle'])
                       else:
                           print("Job didn't match:" +
                                 str(textMessage['JobId']) + ' : ' + str(response['JobId']))
                       # Delete the unknown message. Consider sending to dead letter queue
                       self.sqs.delete_message(QueueUrl=self.sqsQueueUrl,
                                               ReceiptHandle=message['ReceiptHandle'])
   
           print('Done!')
   
       def CreateTopicandQueue(self):
   
           millis = str(int(round(time.time() * 1000)))
   
           # Create SNS topic
           snsTopicName = "AmazonTextractTopic" + millis
   
           topicResponse = self.sns.create_topic(Name=snsTopicName)
           self.snsTopicArn = topicResponse['TopicArn']
   
           # create SQS queue
           sqsQueueName = "AmazonTextractQueue" + millis
           self.sqs.create_queue(QueueName=sqsQueueName)
           self.sqsQueueUrl = self.sqs.get_queue_url(QueueName=sqsQueueName)['QueueUrl']
   
           attribs = self.sqs.get_queue_attributes(QueueUrl=self.sqsQueueUrl,
                                                   AttributeNames=['QueueArn'])['Attributes']
   
           sqsQueueArn = attribs['QueueArn']
   
           # Subscribe SQS queue to SNS topic
           self.sns.subscribe(
               TopicArn=self.snsTopicArn,
               Protocol='sqs',
               Endpoint=sqsQueueArn)
   
           # Authorize SNS to write SQS queue
           policy = """{{
     "Version":"2012-10-17",
     "Statement":[
       {{
         "Sid":"MyPolicy",
         "Effect":"Allow",
         "Principal" : {{"AWS" : "*"}},
         "Action":"SQS:SendMessage",
         "Resource": "{}",
         "Condition":{{
           "ArnEquals":{{
             "aws:SourceArn": "{}"
           }}
         }}
       }}
     ]
   }}""".format(sqsQueueArn, self.snsTopicArn)
   
           response = self.sqs.set_queue_attributes(
               QueueUrl=self.sqsQueueUrl,
               Attributes={
                   'Policy': policy
               })
   
       def DeleteTopicandQueue(self):
           self.sqs.delete_queue(QueueUrl=self.sqsQueueUrl)
           self.sns.delete_topic(TopicArn=self.snsTopicArn)
   
       # Display information about a block
       def DisplayBlockInfo(self, block):
   
           print("Block Id: " + block['Id'])
           print("Type: " + block['BlockType'])
           if 'EntityTypes' in block:
               print('EntityTypes: {}'.format(block['EntityTypes']))
   
           if 'Text' in block:
               print("Text: " + block['Text'])
   
           if block['BlockType'] != 'PAGE':
               print("Confidence: " + "{:.2f}".format(block['Confidence']) + "%")
   
           print('Page: {}'.format(block['Page']))
   
           if block['BlockType'] == 'CELL':
               print('Cell Information')
               print('\tColumn: {} '.format(block['ColumnIndex']))
               print('\tRow: {}'.format(block['RowIndex']))
               print('\tColumn span: {} '.format(block['ColumnSpan']))
               print('\tRow span: {}'.format(block['RowSpan']))
   
               if 'Relationships' in block:
                   print('\tRelationships: {}'.format(block['Relationships']))
   
           print('Geometry')
           print('\tBounding Box: {}'.format(block['Geometry']['BoundingBox']))
           print('\tPolygon: {}'.format(block['Geometry']['Polygon']))
   
           if block['BlockType'] == 'SELECTION_ELEMENT':
               print('    Selection element detected: ', end='')
               if block['SelectionStatus'] == 'SELECTED':
                   print('Selected')
               else:
                   print('Not selected')
   
       def GetResults(self, jobId):
           maxResults = 1000
           paginationToken = None
           finished = False
   
           while finished == False:
   
               response = None
   
               if self.processType == ProcessType.ANALYSIS:
                   if paginationToken == None:
                       response = self.textract.get_document_analysis(JobId=jobId,
                                                                      MaxResults=maxResults)
                   else:
                       response = self.textract.get_document_analysis(JobId=jobId,
                                                                      MaxResults=maxResults,
                                                                      NextToken=paginationToken)
   
               if self.processType == ProcessType.DETECTION:
                   if paginationToken == None:
                       response = self.textract.get_document_text_detection(JobId=jobId,
                                                                            MaxResults=maxResults)
                   else:
                       response = self.textract.get_document_text_detection(JobId=jobId,
                                                                            MaxResults=maxResults,
                                                                            NextToken=paginationToken)
   
               blocks = response['Blocks']
               print('Detected Document Text')
               print('Pages: {}'.format(response['DocumentMetadata']['Pages']))
   
               # Display block information
               for block in blocks:
                   self.DisplayBlockInfo(block)
                   print()
                   print()
   
               if 'NextToken' in response:
                   paginationToken = response['NextToken']
               else:
                   finished = True
   
       def GetResultsDocumentAnalysis(self, jobId):
           maxResults = 1000
           paginationToken = None
           finished = False
   
           while finished == False:
   
               response = None
               if paginationToken == None:
                   response = self.textract.get_document_analysis(JobId=jobId,
                                                                  MaxResults=maxResults)
               else:
                   response = self.textract.get_document_analysis(JobId=jobId,
                                                                  MaxResults=maxResults,
                                                                  NextToken=paginationToken)
   
                   # Get the text blocks
               blocks = response['Blocks']
               print('Analyzed Document Text')
               print('Pages: {}'.format(response['DocumentMetadata']['Pages']))
               # Display block information
               for block in blocks:
                   self.DisplayBlockInfo(block)
                   print()
                   print()
   
                   if 'NextToken' in response:
                       paginationToken = response['NextToken']
                   else:
                       finished = True
   
   
   def main():
       roleArn = ''
       bucket = ''
       document = ''
       region_name = ''
   
       analyzer = DocumentProcessor(roleArn, bucket, document, region_name)
       analyzer.CreateTopicandQueue()
       analyzer.ProcessDocument(ProcessType.DETECTION)
       analyzer.DeleteTopicandQueue()
   
   
   if __name__ == "__main__":
       main()
   ```

------
#### [ Node.JS ]

   En este ejemplo, reemplace el valor de`roleArn`con el ARN del rol de IAM que ha guardado en[Conceder acceso a Amazon Textract a su tema de Amazon SNS](api-async-roles.md#api-async-roles-all-topics). Sustituir los valores de`bucket`y`document`con el nombre del bucket de y el nombre del archivo de documento que especificó en el paso 2 anterior. Sustituir el valor de`processType`con el tipo de procesamiento que quieres utilizar en el documento de entrada. Por último, sustituya el valor de`REGION`con la región en la que opera su cliente.

   ```
    // snippet-start:[sqs.JavaScript.queues.createQueueV3]
   // Import required AWS SDK clients and commands for Node.js
   import { CreateQueueCommand, GetQueueAttributesCommand, GetQueueUrlCommand, 
       SetQueueAttributesCommand, DeleteQueueCommand, ReceiveMessageCommand, DeleteMessageCommand } from  "@aws-sdk/client-sqs";
     import {CreateTopicCommand, SubscribeCommand, DeleteTopicCommand } from "@aws-sdk/client-sns";
     import  { SQSClient } from "@aws-sdk/client-sqs";
     import  { SNSClient } from "@aws-sdk/client-sns";
     import  { TextractClient, StartDocumentTextDetectionCommand, StartDocumentAnalysisCommand, GetDocumentAnalysisCommand, GetDocumentTextDetectionCommand, DocumentMetadata } from "@aws-sdk/client-textract";
     import { stdout } from "process";
     
     // Set the AWS Region.
     const REGION = "us-east-1"; //e.g. "us-east-1"
     // Create SNS service object.
     const sqsClient = new SQSClient({ region: REGION });
     const snsClient = new SNSClient({ region: REGION });
     const textractClient = new TextractClient({ region: REGION });
     
     // Set bucket and video variables
     const bucket = "bucket-name";                                                                                                                  
     const documentName = "document-name";
     const roleArn = "role-arn"
     const processType = "DETECTION"
     var startJobId = ""
     
     var ts = Date.now();
     const snsTopicName = "AmazonTextractExample" + ts;
     const snsTopicParams = {Name: snsTopicName}
     const sqsQueueName = "AmazonTextractQueue-" + ts;
   
     // Set the parameters
     const sqsParams = {
       QueueName: sqsQueueName, //SQS_QUEUE_URL
       Attributes: {
         DelaySeconds: "60", // Number of seconds delay.
         MessageRetentionPeriod: "86400", // Number of seconds delay.
       },
     };
     
     // Process a document based on operation type
     const processDocumment = async (type, bucket, videoName, roleArn, sqsQueueUrl, snsTopicArn) =>
       {
       try
       {
           // Set job found and success status to false initially
         var jobFound = false
         var succeeded = false
         var dotLine = 0
         var processType = type
         var validType = false
   
         if (processType == "DETECTION"){
           var response = await textractClient.send(new StartDocumentTextDetectionCommand({DocumentLocation:{S3Object:{Bucket:bucket, Name:videoName}}, 
             NotificationChannel:{RoleArn: roleArn, SNSTopicArn: snsTopicArn}}))
           console.log("Processing type: Detection")
           validType = true
         }
   
         if (processType == "ANALYSIS"){
           var response = await textractClient.send(new StartDocumentAnalysisCommand({DocumentLocation:{S3Object:{Bucket:bucket, Name:videoName}}, 
             NotificationChannel:{RoleArn: roleArn, SNSTopicArn: snsTopicArn}}))
           console.log("Processing type: Analysis")
           validType = true
         }
   
         if (validType == false){
             console.log("Invalid processing type. Choose Detection or Analysis.")
             return
         }
       // while not found, continue to poll for response
       console.log(`Start Job ID: ${response.JobId}`)
       while (jobFound == false){
         var sqsReceivedResponse = await sqsClient.send(new ReceiveMessageCommand({QueueUrl:sqsQueueUrl, 
           MaxNumberOfMessages:'ALL', MaxNumberOfMessages:10}));
         if (sqsReceivedResponse){
           var responseString = JSON.stringify(sqsReceivedResponse)
           if (!responseString.includes('Body')){
             if (dotLine < 40) {
               console.log('.')
               dotLine = dotLine + 1
             }else {
               console.log('')
               dotLine = 0 
             };
             stdout.write('', () => {
               console.log('');
             });
             await new Promise(resolve => setTimeout(resolve, 5000));
             continue
           }
         }
   
           // Once job found, log Job ID and return true if status is succeeded
           for (var message of sqsReceivedResponse.Messages){
               console.log("Retrieved messages:")
               var notification = JSON.parse(message.Body)
               var rekMessage = JSON.parse(notification.Message)
               var messageJobId = rekMessage.JobId
               if (String(rekMessage.JobId).includes(String(startJobId))){
                   console.log('Matching job found:')
                   console.log(rekMessage.JobId)
                   jobFound = true
                   // GET RESUlTS FUNCTION HERE
                   var operationResults = await GetResults(processType, rekMessage.JobId)
                   //GET RESULTS FUMCTION HERE
                   console.log(rekMessage.Status)
               if (String(rekMessage.Status).includes(String("SUCCEEDED"))){
                   succeeded = true
                   console.log("Job processing succeeded.")
                   var sqsDeleteMessage = await sqsClient.send(new DeleteMessageCommand({QueueUrl:sqsQueueUrl, ReceiptHandle:message.ReceiptHandle}));
               }
               }else{
               console.log("Provided Job ID did not match returned ID.")
               var sqsDeleteMessage = await sqsClient.send(new DeleteMessageCommand({QueueUrl:sqsQueueUrl, ReceiptHandle:message.ReceiptHandle}));
               }
           }
   
       console.log("Done!")
       }
       }catch (err) {
           console.log("Error", err);
         }
     }
   
     // Create the SNS topic and SQS Queue
     const createTopicandQueue = async () => {
       try {
         // Create SNS topic
         const topicResponse = await snsClient.send(new CreateTopicCommand(snsTopicParams));
         const topicArn = topicResponse.TopicArn
         console.log("Success", topicResponse);
         // Create SQS Queue
         const sqsResponse = await sqsClient.send(new CreateQueueCommand(sqsParams));
         console.log("Success", sqsResponse);
         const sqsQueueCommand = await sqsClient.send(new GetQueueUrlCommand({QueueName: sqsQueueName}))
         const sqsQueueUrl = sqsQueueCommand.QueueUrl
         const attribsResponse = await sqsClient.send(new GetQueueAttributesCommand({QueueUrl: sqsQueueUrl, AttributeNames: ['QueueArn']}))
         const attribs = attribsResponse.Attributes
         console.log(attribs)
         const queueArn = attribs.QueueArn
         // subscribe SQS queue to SNS topic
         const subscribed = await snsClient.send(new SubscribeCommand({TopicArn: topicArn, Protocol:'sqs', Endpoint: queueArn}))
         const policy = {
           Version: "2012-10-17",
           Statement: [
             {
               Sid: "MyPolicy",
               Effect: "Allow",
               Principal: {AWS: "*"},
               Action: "SQS:SendMessage",
               Resource: queueArn,
               Condition: {
                 ArnEquals: {
                   'aws:SourceArn': topicArn
                 }
               }
             }
           ]
         };
     
         const response = sqsClient.send(new SetQueueAttributesCommand({QueueUrl: sqsQueueUrl, Attributes: {Policy: JSON.stringify(policy)}}))
         console.log(response)
         console.log(sqsQueueUrl, topicArn)
         return [sqsQueueUrl, topicArn]
     
       } catch (err) {
         console.log("Error", err);
   
       }
     }
   
     const deleteTopicAndQueue = async (sqsQueueUrlArg, snsTopicArnArg) => {
       const deleteQueue = await sqsClient.send(new DeleteQueueCommand({QueueUrl: sqsQueueUrlArg}));
       const deleteTopic = await snsClient.send(new DeleteTopicCommand({TopicArn: snsTopicArnArg}));
       console.log("Successfully deleted.")
     }
   
     const displayBlockInfo = async (block) => {
       console.log(`Block ID: ${block.Id}`)
       console.log(`Block Type: ${block.BlockType}`)
       if (String(block).includes(String("EntityTypes"))){
           console.log(`EntityTypes: ${block.EntityTypes}`)
       }
       if (String(block).includes(String("Text"))){
           console.log(`EntityTypes: ${block.Text}`)
       }
       if (!String(block.BlockType).includes('PAGE')){
           console.log(`Confidence: ${block.Confidence}`)
       }
       console.log(`Page: ${block.Page}`)
       if (String(block.BlockType).includes("CELL")){
           console.log("Cell Information")
           console.log(`Column: ${block.ColumnIndex}`)
           console.log(`Row: ${block.RowIndex}`)
           console.log(`Column Span: ${block.ColumnSpan}`)
           console.log(`Row Span: ${block.RowSpan}`)
           if (String(block).includes("Relationships")){
               console.log(`Relationships: ${block.Relationships}`)
           }
       }
   
       console.log("Geometry")
       console.log(`Bounding Box: ${JSON.stringify(block.Geometry.BoundingBox)}`)
       console.log(`Polygon: ${JSON.stringify(block.Geometry.Polygon)}`)
   
       if (String(block.BlockType).includes('SELECTION_ELEMENT')){
         console.log('Selection Element detected:')
         if (String(block.SelectionStatus).includes('SELECTED')){
           console.log('Selected')
         } else {
           console.log('Not Selected')
         }
   
       }
     }
   
     const GetResults = async (processType, JobID) => {
   
       var maxResults = 1000
       var paginationToken = null
       var finished = false
   
       while (finished == false){
         var response = null
         if (processType == 'ANALYSIS'){
           if (paginationToken == null){
             response = textractClient.send(new GetDocumentAnalysisCommand({JobId:JobID, MaxResults:maxResults}))
         
           }else{
             response = textractClient.send(new GetDocumentAnalysisCommand({JobId:JobID, MaxResults:maxResults, NextToken:paginationToken}))
           }
         }
           
         if(processType == 'DETECTION'){
           if (paginationToken == null){
             response = textractClient.send(new GetDocumentTextDetectionCommand({JobId:JobID, MaxResults:maxResults}))
         
           }else{
             response = textractClient.send(new GetDocumentTextDetectionCommand({JobId:JobID, MaxResults:maxResults, NextToken:paginationToken}))
           }
         }
   
         await new Promise(resolve => setTimeout(resolve, 5000));
         console.log("Detected Documented Text")
         console.log(response)
         //console.log(Object.keys(response))
         console.log(typeof(response))
         var blocks = (await response).Blocks
         console.log(blocks)
         console.log(typeof(blocks))
         var docMetadata = (await response).DocumentMetadata
         var blockString = JSON.stringify(blocks)
         var parsed = JSON.parse(JSON.stringify(blocks))
         console.log(Object.keys(blocks))
         console.log(`Pages: ${docMetadata.Pages}`)
         blocks.forEach((block)=> {
           displayBlockInfo(block)
           console.log()
           console.log()
         })
   
         //console.log(blocks[0].BlockType)
         //console.log(blocks[1].BlockType)
   
   
         if(String(response).includes("NextToken")){
           paginationToken = response.NextToken
         }else{
           finished = true
         }
       }
   
     }
   
   
     // DELETE TOPIC AND QUEUE
     const main = async () => {
       var sqsAndTopic = await createTopicandQueue();
       var process = await processDocumment(processType, bucket, documentName, roleArn, sqsAndTopic[0], sqsAndTopic[1])
       var deleteResults = await deleteTopicAndQueue(sqsAndTopic[0], sqsAndTopic[1])
     }
   
   main()
   ```

------

1. Ejecute el código. La operación podría llevar algún tiempo. Una vez terminada, se muestra una lista de bloques para el texto detectado o analizado.

# Notificación de resultados de Amazon Textract
<a name="async-notification-payload"></a>

Amazon Textract publica los resultados de una solicitud de análisis de Amazon Textract, incluido el estado de realización, en un tema de Amazon Simple Notification Service (Amazon SNS). Para obtener la notificación de un tema de Amazon SNS, utilice una cola de Amazon SQS o unAWS Lambdafunción. Para obtener más información, consulte [Llamar a operaciones asíncronas de Amazon Textract](api-async.md). Para ver un ejemplo, consulte [Detección o análisis de texto en un documento de varias páginas](async-analyzing-with-sqs.md).

Los resultados tienen el siguiente formato JSON:

```
{
  "JobId": "String",
  "Status": "String",
  "API": "String",
  "JobTag": "String",
  "Timestamp": Number,
  "DocumentLocation": {
    "S3ObjectName": "String",
    "S3Bucket": "String"
  }
}
```

En esta tabla se describen los diferentes parámetros de una respuesta de Amazon Textract Texact.


| Parámetro | Descripción | 
| --- | --- | 
|  JobId  |  Identificador exclusivo que Amazon Textract asigna al trabajo. Coincide con un identificador de trabajo que devuelve desde un`Start`operación, tales como[StartDocumentTextDetection](API_StartDocumentTextDetection.md).  | 
|  Estado  |  El estado del trabajo. Los valores válidos son Correctos, Fallados o Error.  | 
|  API  |  La operación de Amazon Textract utilizada para analizar el documento de entrada, como por ejemplo[StartDocumentTextDetection](API_StartDocumentTextDetection.md)o[StartDocumentAnalysis](API_StartDocumentAnalysis.md).  | 
|  JobTag  |  El identificador especificado por el usuario del trabajo. Especificas`JobTag`en una llamada al`Start`operación, tales como[StartDocumentTextDetection](API_StartDocumentTextDetection.md).  | 
|  Marca temporal  |  La marca de tiempo de Unix que indica cuándo finalizó el trabajo, se devuelve en milisegundos.  | 
|  Ubicación del documento  |  Detalles sobre el documento que se procesó. Incluye el nombre de archivo y el bucket de Amazon S3 en el que está almacenado el archivo.  | 