

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Processando documentos com operações assíncronas
<a name="async"></a>

Amazon Textract pode detectar e analisar texto em documentos de várias páginas que estão em formato PDF ou TIFF. Isso inclui faturas e recibos. O processamento de documentos de várias páginas é uma operação assíncrona. O processamento assíncrono de documentos é útil para processar documentos grandes de várias páginas. Por exemplo, um arquivo PDF com mais de 1.000 páginas leva algum tempo para ser processado. O processamento do arquivo PDF de forma assíncrona permite que seu aplicativo conclua outras tarefas enquanto aguarda a conclusão do processo. 

Esta seção aborda como você pode usar o Amazon Textract para detectar e analisar texto de forma assíncrona em um documento de várias páginas ou de uma única página. Documentos com várias páginas devem estar em formato PDF ou TIFF. Documentos de página única processados com operações assíncronas podem estar no formato JPEG, PNG, TIFF ou PDF.

Você pode usar as operações assíncronas do Amazon Textract para as seguintes finalidades:
+ Detecção de texto — Você pode detectar linhas e palavras em um documento de várias páginas. As operações assíncronas são[StartDocumentTextDetection](API_StartDocumentTextDetection.md)e[GetDocumentTextDetection](API_GetDocumentTextDetection.md). Para obter mais informações, consulte [Detectar texto](how-it-works-detecting.md).
+ Análise de texto — Você pode identificar relacionamentos entre o texto detectado em um documento de várias páginas. As operações assíncronas são[StartDocumentAnalysis](API_StartDocumentAnalysis.md)e[GetDocumentAnalysis](API_GetDocumentAnalysis.md). Para obter mais informações, consulte [Analisar documentos](how-it-works-analyzing.md).
+ Análise de despesas — Você pode identificar relacionamentos de dados em faturas e recebimentos de várias páginas. Amazon Textract trata cada fatura ou uma página de recibo de um documento de várias páginas como um recibo individual ou uma fatura. Ele não retém o contexto de uma página para outra de um documento de várias páginas. As operações assíncronas são[StartExpenseAnalysis](API_StartExpenseAnalysis.md)e[GetExpenseAnalysis](API_GetExpenseAnalysis.md). Para obter mais informações, consulte [Analisando faturas e recibos](invoices-receipts.md).

**Topics**
+ [Chamando operações assíncronas do Amazon Textract](api-async.md)
+ [Configurando o Amazon Textract para operações assíncronas](api-async-roles.md)
+ [Detectando ou analisando texto em um documento de várias páginas](async-analyzing-with-sqs.md)
+ [Notificação de resultados do Amazon Textract](async-notification-payload.md)

# Chamando operações assíncronas do Amazon Textract
<a name="api-async"></a>

O Amazon Textract fornece uma API assíncrona que você pode usar para processar documentos de várias páginas em formato PDF ou TIFF. Você também pode usar operações assíncronas para processar documentos de página única que estão no formato JPEG, PNG, TIFF ou PDF. 

As informações neste tópico usam operações de detecção de texto para mostrar como usar operações assíncronas do Amazon Textract. A mesma abordagem funciona com as operações de análise de texto do[StartDocumentAnalysis](API_StartDocumentAnalysis.md)e[GetDocumentAnalysis](API_GetDocumentAnalysis.md). Também funciona da mesma maneira com[StartExpenseAnalysis](API_StartExpenseAnalysis.md)e[GetExpenseAnalysis](API_GetExpenseAnalysis.md). 

Para ver um exemplo, consulte [Detectando ou analisando texto em um documento de várias páginas](async-analyzing-with-sqs.md).

Amazon Textract processa assíncrona um documento armazenado em um bucket do Amazon S3. Você começa a processar chamando um`Start`operação, como[StartDocumentTextDetection](API_StartDocumentTextDetection.md). O status de conclusão da solicitação é publicada em um tópico do Amazon Simple Notification Service (Amazon SNS). Para obter o status de conclusão do tópico do Amazon SNS, use uma fila do Amazon Simple Queue Service (Amazon SQS) ou umaAWS Lambdafunção. Ao receber o status de conclusão, chame uma operação `Get`, como a [GetDocumentTextDetection](API_GetDocumentTextDetection.md) para obter os resultados da solicitação. 

Os resultados de chamadas assíncronas são criptografados e armazenados por 7 dias em um bucket de propriedade do Amazon Textract por padrão, a menos que você especifique um bucket do Amazon S3 usando uma operação`OutputConfig`Argumento.

A tabela a seguir mostra as operações Iniciar e Get correspondentes para os diferentes tipos de processamento assíncrono suportados pelo Amazon Textract:


**Iniciar/obter operações de API para operações assíncronas do Amazon Textract**  

| Tipo de processamento | API Iniciar | Obter API | 
| --- | --- | --- | 
| Detecção de texto | StartDocumentTextDetection | GetDocumentTextDetection | 
| Análise de texto | StartDocumentAnalysis | GetDocumentAnalysis | 
| Análise de despesas | StarTExpenseAnalysis | GetExpenseAnalysis | 

Para um exemplo que usaAWS Lambdafunções, consulte[Processamento de documentos em grande escala com o Amazon Textract](https://github.com/aws-samples/amazon-textract-serverless-large-scale-document-processing).

O diagrama a seguir mostra o processo para detectar o texto do documento em uma imagem de documento armazenada em um bucket do Amazon S3. No diagrama, uma fila do Amazon SQS obtém o status de conclusão do tópico do Amazon SNS. 

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


O processo exibido pelo diagrama anterior é o mesmo para analisar texto e faturas/recibos. Você começa a analisar o texto chamando[StartDocumentAnalysis](API_StartDocumentAnalysis.md)e comece a analisar faturas/recibos ligando[StartExpenseAnalysis](API_StartExpenseAnalysis.md)Você obtém os resultados ligando[GetDocumentAnalysis](API_GetDocumentAnalysis.md)ou[GetExpenseAnalysis](API_GetExpenseAnalysis.md)respectivamente.

## Iniciar a detecção de texto
<a name="api-async-start"></a>

Você pode iniciar uma solicitação de detecção de texto do Amazon Textract chamando[StartDocumentTextDetection](API_StartDocumentTextDetection.md). Veja a seguir um exemplo de uma solicitação JSON que é transmitida por `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"
}
```

O parâmetro de entrada`DocumentLocation`fornece o nome do arquivo do documento e o bucket do Amazon S3 do qual recuperá-lo.`NotificationChannel`contém o Nome de recurso da Amazon (ARN) do tópico do Amazon SNS que o Amazon Textract notifica quando a solicitação de detecção de texto é concluída. O tópico do Amazon SNS deve estar na mesma região da AWS que o endpoint do Amazon Textract que você está chamando.`NotificationChannel`também contém o ARN para uma função que permite que o Amazon Textract publique no tópico do Amazon SNS. Você concede permissões de publicação Amazon Textract para os tópicos do Amazon SNS criando uma função de serviço do IAM. Para obter mais informações, consulte [Configurando o Amazon Textract para operações assíncronas](api-async-roles.md).

Você também pode especificar um parâmetro de entrada opcional,`JobTag`, que permite identificar o trabalho ou grupos de trabalhos no status de conclusão que é publicada no tópico do Amazon SNS. Por exemplo, você pode usar`JobTag`para identificar o tipo de documento que está sendo processado, como um formulário fiscal ou recibo.

Para evitar a duplicação acidental de trabalhos de análise, você pode opcionalmente fornecer um token de idempotência, `ClientRequestToken`. Se você fornecer um valor para`ClientRequestToken`, o`Start`A operação retorna o mesmo`JobId`para várias chamadas idênticas ao`Start`operação, como`StartDocumentTextDetection`. Um token `ClientRequestToken` tem uma vida útil de 7 dias. Depois de 7 dias, você pode reutilizá-lo. Se você reutilizar o token durante a vida útil, o seguinte acontecerá: 
+ Se você reutilizar o token com a mesma operação `Start` e os mesmos parâmetros de entrada, o mesmo `JobId` será retornado. O trabalho não é realizado novamente, e o Amazon Textract não envia um status de conclusão ao tópico do Amazon SNS registrado.
+ Se você reutilizar o token com a mesma operação `Start` e uma pequena alteração no parâmetro de entrada, você receberá uma exceção `idempotentparametermismatchexception` (código de status HTTP: 400).
+ Se você reutilizar o token com uma operação `Start` diferente, a operação será bem-sucedida.

Outro parâmetro opcional disponível é`OutputConfig`, que permite ajustar onde sua saída será colocada. Por padrão, o Amazon Textract armazenará os resultados internamente e só poderá ser acessado pelas operações Get API. com`OutputConfig`habilitado, você pode definir o nome do bucket para o qual a saída será enviada e o prefixo do arquivo dos resultados, onde você pode baixar seus resultados. Além disso, você pode definir o`KMSKeyID`parâmetro para uma chave gerenciada pelo cliente para criptografar sua saída. Sem esse conjunto de parâmetros, o Amazon Textract criptografará o lado do servidor usando oChave gerenciada pela AWSpara Amazon S3

**nota**  
Antes de usar esse parâmetro, certifique-se de ter a permissão PutObject para o bucket de saída. Além disso, certifique-se de ter as permissões Decrypt, ReEnCrypt, GenerateDataKey e DescribeKey para oAWS KMSchave se você decidir usá-lo.

A resposta à operação `StartDocumentTextDetection` é um identificador de trabalho (`JobId`). Usar o`JobId`Para rastrear solicitações e obter os resultados da análise após o Amazon Textract publicar o status de conclusão no tópico do Amazon SNS. Veja um exemplo a seguir:

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

Se você iniciar muitos trabalhos simultaneamente, ligue para`StartDocumentTextDetection`RAISE`LimitExceededException`Exceção (código de status HTTP: 400) até que o número de trabalhos simultâneos fique abaixo do limite de serviço do Amazon Textract. 

Se você acredita que exceções LimitExceededException estão sendo geradas com intermitências de atividade, considere a possibilidade de usar uma fila do Amazon SQS para gerenciar as solicitações recebidas. ContatoAWSSupport se você acredita que o número médio de solicitações simultâneas não pode ser gerenciado por uma fila do Amazon SQS e você ainda está recebendo`LimitExceededException`exceções. 

## Obter o status de conclusão de uma solicitação de análise do Amazon Textract
<a name="api-async-get-status"></a>

Amazon Textract envia uma notificação de conclusão de análise para o tópico do Amazon SNS registrado. A notificação inclui o identificador do trabalho e o status de conclusão da operação em uma string JSON. Uma solicitação de detecção de texto bem-sucedida tem um`SUCCEEDED`Status. Por exemplo, o resultado a seguir mostra o processamento bem-sucedido de um trabalho de detecção de texto.

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

Para obter mais informações, consulte [Notificação de resultados do Amazon Textract](async-notification-payload.md).

Para obter as informações de status publicadas no tópico do Amazon SNS pelo Amazon Textract, use uma das seguintes opções:
+ **AWS Lambda**— Você pode assinar umAWS LambdaFunção do que você grava em um tópico do Amazon SNS. A função é chamada quando o Amazon Textract notifica o tópico do Amazon SNS que a solicitação foi concluída. Use uma função do Lambda se desejar que o código do lado do servidor processe os resultados de uma solicitação de detecção de texto. Por exemplo, você pode usar o código do lado do servidor para anotar a imagem ou criar um relatório no texto detectado antes de retornar as informações para um aplicativo cliente.
+ **Amazon SQS**— Você pode inscrever uma fila do Amazon SQS em um tópico do Amazon SNS. Em seguida, pesquise a fila do Amazon SQS para recuperar o status de conclusão publicado pelo Amazon Textract quando uma solicitação de detecção de texto é concluída. Para obter mais informações, consulte [Detectando ou analisando texto em um documento de várias páginas](async-analyzing-with-sqs.md). Use uma fila do Amazon SQS se desejar chamar as operações Amazon Textract somente a partir de um aplicativo cliente. 

**Importante**  
Nós não recomendamos obter o status de conclusão da solicitação chamando repetidamente o Amazon Textract`Get`operação. Isso ocorre porque o Amazon Textract acelera o`Get`Se muitas solicitações forem realizadas. Se você estiver processando vários documentos ao mesmo tempo, é mais simples e mais eficiente monitorar uma fila do SQS para a notificação de conclusão do que pesquisar no Amazon Textract para o status de cada trabalho individualmente.

## Obtendo resultados de detecção de texto Amazon Textract
<a name="api-async-get"></a>

Para obter os resultados de uma solicitação de detecção de texto, primeiro verifique se o status de conclusão que é recuperado do tópico do Amazon SNS é`SUCCEEDED`. Em seguida, chame `GetDocumentTextDetection`, que transmite o valor `JobId` que é retornado de `StartDocumentTextDetection`. O JSON solicitado é semelhante ao exemplo a seguir:

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

`JobId`é o identificador da operação de detecção de texto. Como a detecção de texto pode gerar grandes quantidades de dados, use`MaxResults`Para especificar o número máximo de resultados a serem retornados em um único`Get`operação. O valor padrão para`MaxResults`É 1.000. Se você especificar um valor maior que 1.000, somente 1.000 resultados serão retornados. Se a operação não retornar todos os resultados, um token de paginação para a próxima página será retornado. Para obter a próxima página de resultados, especifique o token no`NextToken`parâmetro . 

**nota**  
O Amazon Textract retém os resultados de operações assíncronas por 7 dias. Você não pode recuperar os resultados após esse período.

O`GetDocumentTextDetection`O JSON solicitado da operação é semelhante ao seguinte. O número total de páginas detectadas é retornado em`DocumentMetadata`. O texto detectado é retornado no`Blocks`matriz. Para obter mais informações sobre o`Block`objetos, consulte[Objetos de resposta de detecção de texto e análise de](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
        }
    ]
}
```

# Configurando o Amazon Textract para operações assíncronas
<a name="api-async-roles"></a>

Os procedimentos a seguir mostram como configurar o Amazon Textract para usar com um tópico do Amazon Simple Notification Service (Amazon SNS) e em uma fila do Amazon Simple Queue Service (Amazon SQS).

**nota**  
Se você estiver usando essas instruções para configurar o[Detectando ou analisando texto em um documento de várias páginas](async-analyzing-with-sqs.md)Por exemplo, você não precisa executar as etapas 3 — 6. O exemplo inclui código para criar e configurar o tópico do Amazon SNS e a fila do Amazon SQS.

**Para configurar o Amazon Textract**

1. Configurar umAWSconta para acessar o Amazon Textract. Para obter mais informações, consulte [Etapa 1: Configurar uma conta da AWS e criar um usuário do IAM](setting-up.md).

   Certifique-se de que o usuário tenha pelo menos as seguintes permissões:
   + AmazonTextractFullAccess
   + AmazonS3ReadOnlyAccess
   + AmazonSNSFullAccess
   + AmazonSQSFullAccess

1. Instale e configure o SDK da AWS necessário. Para obter mais informações, consulte [Etapa 2: Configurar aAWS CLIeAWSSDKs da](setup-awscli-sdk.md). 

1. [Criar um tópico do Amazon SNS](https://docs.aws.amazon.com/sns/latest/dg/sns-tutorial-create-topic.html). Anteca o nome do tópico com*AmazonTextact*. Anote o nome de recurso da Amazon (ARN) do tópico. Verifique se o tópico do está na mesma região do que oAWSO endpoint do que você está usando com sua conta da AWS.

1. [Criar uma fila padrão do Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)usando o[Console do Amazon SQS](https://console.aws.amazon.com/sqs/). Anotar o ARN da fila.

1. [Inscreva a fila no tópico](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-subscribe-queue-sns-topic.html) criado na etapa 3.

1. [Conceda permissão ao tópico do Amazon SNS para enviar mensagens à fila do Amazon SQS](https://docs.aws.amazon.com/sns/latest/dg/subscribe-sqs-queue-to-sns-topic.html).

1. Crie uma função de serviço do IAM para dar ao Amazon Textract acesso aos tópicos do Amazon SNS. Observe o nome de recurso da Amazon (ARN) da função de serviço. Para obter mais informações, consulte [Dando acesso ao Amazon Textract ao seu tópico do Amazon SNS](#api-async-roles-all-topics).

1. [Adicione a seguinte política em linha](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#embed-inline-policy-console)Para o usuário do IAM que você criou na etapa 1. 

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

   Dê um nome à política em linha.

1. Agora, você pode executar os exemplos no[Detectando ou analisando texto em um documento de várias páginas](async-analyzing-with-sqs.md).

## Dando acesso ao Amazon Textract ao seu tópico do Amazon SNS
<a name="api-async-roles-all-topics"></a>

Amazon Textract precisa de permissão para enviar uma mensagem ao tópico do Amazon SNS quando uma operação assíncrona for concluída. Use uma função de serviço do IAM para dar ao Amazon Textract acesso ao tópico do Amazon SNS. 

 Ao criar o tópico do Amazon SNS, você deve anexar o nome do tópico com**AmazonTextract**—por exemplo,**AmazonTextractMyTopicName**. 

1. Faça login no console do IAM ([https://console.aws.amazon.com/iam](https://console.aws.amazon.com/iam)).

1. No painel de navegação, selecione **Roles**.

1. Selecione **Create role**.

1. Em **Select type of trusted entity (Selecionar tipo de entidade confiável)**, escolha **AWS service (Serviço da AWS)**. 

1. para o**Escolha o serviço que usará esta função**, escolha**Textract**.

1. Selecione **Next** (Próximo): **Permissions**

1. Verificar se o**AmazonTextractServiceRole**a política foi incluída na lista de políticas anexadas. Para exibir a política na lista, insira parte do nome da política no**Políticas de filtros**.

1. Selecione **Next** (Próximo): **Tags**.

1. Você não precisa adicionar tags, então selecione**Próximo: Análise**.

1. Na seção **Review (Revisar)**, em **Role Name (Nome da função)**, insira um nome para a função (por exemplo, `TextractRole`). Dentro**Descrição de função**, atualize a descrição da função e, em seguida, escolha**Criar função do**.

1. Escolha a nova função para abrir a página de detalhes da função.

1. Em **Summary (Resumo)**, copie o valor do **Role ARN (ARN da função)** e salve-o.

1. Escolha **Trust relationships (Relações de confiança)**.

1. Selecione**Editar relação de confiança**e garanta que a política de confiança seja a seguinte.

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

1. Escolha **Update Trust Policy**.

# Detectando ou analisando texto em um documento de várias páginas
<a name="async-analyzing-with-sqs"></a>

Este procedimento mostra como detectar ou analisar texto em um documento de várias páginas usando operações de detecção do Amazon Textract, um documento armazenado em um bucket do Amazon S3, um tópico do Amazon SNS e uma fila do Amazon SQS. O processamento de documentos de várias páginas é uma operação assíncrona. Para obter mais informações, consulte [Chamando operações assíncronas do Amazon Textract](api-async.md).

Você pode escolher o tipo de processamento que deseja que o código faça: detecção de texto, análise de texto ou análise de despesas. 

Os resultados do processamento são retornados em uma matriz de[Block](API_Block.md)Objetos, que diferem dependendo do tipo de processamento usado.

 Para detectar texto em documentos de várias páginas ou analisar, faça o seguinte:

1. Crie o tópico do Amazon SNS e a fila do Amazon SQS.

1. Assinar a fila do tópico do.

1. Conceda permissão ao tópico do para enviar mensagens à fila do.

1. Comece a processar o documento. Use a operação apropriada para o tipo de análise escolhido:
   + [StartDocumentTextDetection](API_StartDocumentTextDetection.md)para tarefas de detecção de texto.
   + [StartDocumentAnalysis](API_StartDocumentAnalysis.md)para tarefas de análise de texto.
   + [StartExpenseAnalysis](API_StartExpenseAnalysis.md)para tarefas de análise de despesas.

1. Obtenha o status de conclusão a partir da fila do Amazon SQS. O código de exemplo rastreia o identificador da tarefa (`JobId`) que é retornado pelo`Start`operação. Ele somente obtém os resultados para identificadores de trabalho correspondentes que são lidos a partir do status de conclusão. Isso é importante se outros aplicativos estiverem usando a mesma fila do e tópico do. Para simplificar, o exemplo exclui trabalhos não correspondentes. Considere adicionar as tarefas excluídas a uma fila de mensagens mortas do Amazon SQS para mais investigações.

1. Obtenha e exiba os resultados do processamento chamando a operação apropriada para o tipo de análise escolhido:
   + [GetDocumentTextDetection](API_GetDocumentTextDetection.md)para tarefas de detecção de texto.
   + [GetDocumentAnalysis](API_GetDocumentAnalysis.md)para tarefas de análise de texto.
   + [GetExpenseAnalysis](API_GetExpenseAnalysis.md)para tarefas de análise de despesas.

1. Exclua o tópico do Amazon SNS e a fila do Amazon SQS.

## Executando operações assíncronas
<a name="async-prerequisites"></a>

O código de exemplo para este procedimento é fornecido em Java, Python e oAWS CLI. Antes de começar, instale o apropriadoAWSSDK. Para obter mais informações, consulte [Etapa 2: Configurar aAWS CLIeAWSSDKs da](setup-awscli-sdk.md). 

**Para detectar ou analisar texto em um documento de várias páginas**

1. Configure o acesso de usuário ao Amazon Textract e configure o acesso do Amazon Textract ao Amazon SNS. Para obter mais informações, consulte [Configurando o Amazon Textract para operações assíncronas](api-async-roles.md). Para concluir este procedimento, você precisa de um documento de várias páginas em formato PDF. Ignorar as etapas 3 — 6 porque o código de exemplo cria e configura o tópico do Amazon SNS e a fila do Amazon SQS. Se completNo exemplo da CLI, você não precisa configurar uma fila SQS. 

1. Faça upload de um arquivo de documento de várias páginas em formato PDF ou TIFF para o seu bucket do Amazon S3. (Documentos de página única em formato JPEG, PNG, TIFF ou PDF também podem ser processados). 

   Para obter instruções, consulte[Fazer upload de objetos no Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/UploadingObjectsintoAmazonS3.html)no*Guia do usuário do Amazon Simple Storage Service*.

1. Use o seguinteAWS SDK para Java, SDK for Python (Boto3) ouAWS CLIcódigo para detectar texto ou analisar texto em um documento de várias páginas. No`main`função:
   + Substitua o valor de`roleArn`Com o ARN da função do IAM no qual você salvou[Dando acesso ao Amazon Textract ao seu tópico do Amazon SNS](api-async-roles.md#api-async-roles-all-topics). 
   + Substitua os valores de`bucket`e`document`Com o bucket e o nome do arquivo do documento especificado na etapa 2. 
   + Substitua o valor do`type`parâmetro de entrada do`ProcessDocument`Função com o tipo de processamento que você deseja fazer. Usar o`ProcessType.DETECTION`para detectar texto. Usar o`ProcessType.ANALYSIS`para analisar texto. 
   + Para o exemplo Python, substitua o valor de`region_name`com a região em que seu cliente está operando.

   Para oAWS CLIPor exemplo, faça o seguinte:
   + Ao ligar[StartDocumentTextDetection](API_StartDocumentTextDetection.md), substitua o valor de`bucket-name`Com o nome do seu bucket do S3 e substitua`file-name`Com o nome do arquivo especificado na etapa 2. Especifique a região do bucket substituindo`region-name`Com o nome da sua região. Observe que o exemplo da CLI não faz uso do SQS. 
   + Ao ligar[GetDocumentTextDetection](API_GetDocumentTextDetection.md)substituir`job-id-number`com o`job-id`Retornado por[StartDocumentTextDetection](API_StartDocumentTextDetection.md). Especifique a região do bucket substituindo`region-name`Com o nome da sua região.

------
#### [ 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 ]

   EsseAWS CLIO comando inicia a detecção assíncrona de texto em um documento especificado. Ele retorna um`job-id`que pode ser usado para retreviver os resultados da detecção. 

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

   EsseAWS CLIcomando retorna os resultados de uma operação assíncrona do Amazon Textract quando fornecido com um`job-id`. 

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

   Se você estiver acessando a CLI em um dispositivo Windows, use aspas duplas em vez de aspas simples e escape das aspas duplas internas por barra invertida (ou seja,\$1) para resolver quaisquer erros de analisador que você possa encontrar. Para obter um exemplo, veja abaixo

   ```
   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 ]

   Neste exemplo, substitua o valor de`roleArn`Com o ARN da função do IAM no qual você salvou[Dando acesso ao Amazon Textract ao seu tópico do Amazon SNS](api-async-roles.md#api-async-roles-all-topics). Substitua os valores de`bucket`e`document`Com o bucket e o nome do arquivo do documento especificado na etapa 2 acima. Substitua o valor de`processType`com o tipo de processamento que você gostaria de usar no documento de entrada. Finalmente, substitua o valor de`REGION`com a região em que seu cliente está operando.

   ```
    // 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. Execute o código. A operação pode demorar um pouco para ser concluída. Depois de ser concluída, uma lista de blocos para texto detectado ou analisado é exibida.

# Notificação de resultados do Amazon Textract
<a name="async-notification-payload"></a>

O Amazon Textract publica os resultados de uma solicitação de análise do Amazon Textract, incluindo o status de conclusão, em um tópico do Amazon Simple Notification Service (Amazon SNS). Para obter a notificação de um tópico do Amazon SNS, use uma fila do Amazon SQS ou umaAWS Lambdafunção. Para obter mais informações, consulte [Chamando operações assíncronas do Amazon Textract](api-async.md). Para ver um exemplo, consulte [Detectando ou analisando texto em um documento de várias páginas](async-analyzing-with-sqs.md).

Os resultados possuem o seguinte formato JSON:

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

Esta tabela descreve os diferentes parâmetros dentro de uma resposta do Amazon Textract.


| Parâmetro | Descrição | 
| --- | --- | 
|  JobId  |  O identificador exclusivo que o Amazon Textract atribui ao trabalho. Ele corresponde a um identificador de trabalho que é retornado de um`Start`operação, como[StartDocumentTextDetection](API_StartDocumentTextDetection.md).  | 
|  Status  |  O status do trabalho. Os valores válidos são bem-sucedidos, com falha ou erro.  | 
|  API  |  A operação do Amazon Textract usada para analisar o documento de entrada, como[StartDocumentTextDetection](API_StartDocumentTextDetection.md)ou[StartDocumentAnalysis](API_StartDocumentAnalysis.md).  | 
|  JobTag  |  O identificador especificado pelo usuário para a tarefa. Você especifica`JobTag`em uma chamada para o`Start`operação, como[StartDocumentTextDetection](API_StartDocumentTextDetection.md).  | 
|  Timestamp  |  O carimbo de data/hora Unix que indica quando o trabalho foi concluído, retornado em milissegundos.  | 
|  DocumentLocation  |  Detalhes sobre o documento que foi processado. Inclui o nome do arquivo e o bucket do Amazon S3 no qual o arquivo está armazenado.  | 