View a markdown version of this page

Extração e envio de texto para o AWS Comprehend para análise - Amazon Textract

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á.

Extração e envio de texto para o AWS Comprehend para análise

O Amazon Textract permite que você inclua detecção e análise de texto de documentos em seus aplicativos. Com o Amazon Textract, você pode extrair texto de vários tipos diferentes de documentos usando o processamento síncrono e assíncrono de documentos. O texto extraído pode então ser salvo em um arquivo ou banco de dados ou enviado para outro AWS serviço para processamento posterior.

Neste tutorial, você executa um fluxo de trabalho comum de ponta a ponta. Esse fluxo de trabalho envolve:

  • Processamento de vários documentos de entrada com o Amazon Textract

  • Fornecendo o texto extraído ao Amazon Comprehend para análise

  • Salvando o texto analisado e os dados da análise em um bucket do Amazon Simple Storage Service (S3)

Você usa o AWS SDK para Python neste tutorial. Você também pode ver o GitHub repositório de exemplos do SDK de AWS documentação para ver mais tutoriais em Python.

Pré-requisitos

Antes de começar este tutorial, você precisará instalar o Python e concluir as etapas necessárias para configurar o SDK do Python. AWS Além disso, confira se você:

Iniciando a detecção assíncrona de texto de documentos

Você pode extrair o texto dos seus documentos e depois analisar o texto extraído com um serviço como o Amazon Comprehend. O Textract suporta a extração de texto de documentos de várias páginas por meio de operações assíncronas, que servem para processar documentos grandes de várias páginas. O processamento assíncrono de um arquivo PDF permite que seu aplicativo conclua outras tarefas enquanto aguarda a conclusão do processo. Esta seção demonstrará como importar seus documentos de um bucket do Amazon S3 e fornecê-los à operação assíncrona de detecção de texto do Textract.

Este tutorial pressupõe que você usará o Amazon S3 para armazenar os arquivos dos quais deseja extrair texto. Você começará criando uma classe e funções que detectam o texto em seus documentos de entrada. Seu aplicativo precisará se conectar ao cliente Textract, bem como aos clientes Amazon SQS e Amazon SNS para monitorar o status de conclusão do trabalho assíncrono.

  1. Comece escrevendo o código para criar um tópico do Amazon SNS e uma fila do Amazon SQS.

    O exemplo de código a seguir cria uma DocumentProcessor classe que se conecta aos três serviços necessários e, em seguida, cria uma fila do Amazon SQS e um tópico do Amazon SNS. O tópico do Amazon SNS é usado para fornecer informações sobre o status de conclusão do trabalho para uma fila do Amazon SQS, que será pesquisada para obter o status de conclusão de um trabalho. Também há métodos para excluir a fila do Amazon SQS e o tópico do Amazon SNS quando o trabalho for concluído e os recursos não forem mais necessários.

    import boto3 import json import sys import time 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 # Instantiates necessary AWS clients session = boto3.Session(profile_name='profile-name', region_name='self.region_name') self.textract = session.client('textract', region_name=self.region_name) self.sqs = session.client('sqs', region_name=self.region_name) self.sns = session.client('sns', region_name=self.region_name) 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)
  2. Escreva o código para chamar a StartDocumentTextDetection operação e obter os resultados da operação.

    A DocumentProcessor classe também precisará de métodos para:

    • Ligue para a StartDocumentTextDetection operação

    • Consulte um Amazon SQS para saber o status de conclusão do trabalho

    • Recupere os resultados do trabalho depois de concluído o processamento

    O código a seguir cria os GetResults métodos ProcessDocument e que chamam StartDocumentTextDetection e obtêm o texto extraído, respectivamente.

    def ProcessDocument(self): # Checks if job found jobFound = False # Starts the text detection operation on the documents in the provided bucket # Sends status to supplied SNS topic arn 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') print('Start Job Id: ' + response['JobId']) dotLine = 0 while jobFound == False: sqsResponse = self.sqs.receive_message(QueueUrl=self.sqsQueueUrl, MessageAttributeNames=['ALL'], MaxNumberOfMessages=10) # Waits until messages are found in the SQS queue 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 # Checks for a completed job that matches the jobID in the response from # StartDocumentTextDetection for message in sqsResponse['Messages']: notification = json.loads(message['Body']) textMessage = json.loads(notification['Message']) if str(textMessage['JobId']) == response['JobId']: print('Matching Job Found:' + textMessage['JobId']) jobFound = True text_data = self.GetResults(textMessage['JobId']) self.sqs.delete_message(QueueUrl=self.sqsQueueUrl, ReceiptHandle=message['ReceiptHandle']) return text_data 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!') # gets the results of the completed text detection job # checks for pagination tokens to determine if there are multiple pages in the input doc def GetResults(self, jobId): maxResults = 1000 paginationToken = None finished = False while finished == False: response = None 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'] # List to hold detected text detected_text = [] # Display block information and add detected text to list for block in blocks: if 'Text' in block and block['BlockType'] == "LINE": detected_text.append(block['Text']) # If response contains a next token, update pagination token if 'NextToken' in response: paginationToken = response['NextToken'] else: finished = True return detected_text
  3. Salve o código acima em um arquivo chamadodetectFileAsync.py.

    Você usa esse arquivo na próxima seção para lidar com a detecção de texto em seus documentos de entrada.

Processando seus documentos e enviando o texto para Comprehend

Seu aplicativo usará a classe que você criou na seção de procedimentos para:

  • leia documentos do seu bucket Amazon S3

  • extraia o texto nesses documentos

  • envie o texto para o Amazon Comprehend para análise

Você começa criando algumas funções que utilizam o Amazon Comprehend para analisar o texto detectado em seus documentos de entrada. Um tipo comum de análise de texto é a análise de sentimentos, que visa capturar o efeito de uma declaração (seja ela positiva, negativa ou neutra). Você também pode realizar a detecção de entidades e de frases-chave nos dados.

O código abaixo pega o texto detectado e invoca a BatchDetectSentiment operação do Amazon Comprehend para realizar uma análise de sentimentos.

  1. Escreva o código para realizar uma análise de sentimentos no texto detectado.

    from detectFileAsync import DocumentProcessor import boto3 import pandas as pd # Detect sentiment def sentiment_analysis(detected_text, lang): comprehend = boto3.client("comprehend") detect_sent_response = comprehend.batch_detect_sentiment( TextList=detected_text, LanguageCode=lang) # Lists to hold sentiment labels and sentiment scores sentiments = [] pos_score = [] neg_score = [] neutral_score = [] mixed_score = [] # for all results add the Sentiment label and sentiment scores to lists for res in detect_sent_response['ResultList']: sentiments.append(res['Sentiment']) print(res['SentimentScore']) print(type(res['SentimentScore'])) for key, val in res['SentimentScore'].items(): if key == "Positive": pos_score.append(val) if key == "Negative": neg_score.append(val) if key == "Neutral": neutral_score.append(val) if key == "Mixed": mixed_score.append(val) return sentiments, pos_score, neg_score, neutral_score, mixed_score

    Talvez você também queira realizar outras operações de análise, como detecção de entidade ou detecção de frase-chave, no texto detectado. Você pode escrever as funções para realizar essas operações de análise em seu texto, assim como fez com a operação de análise de sentimentos em andamento.

  2. Escreva o código para realizar a detecção de entidades no texto detectado.

    # detect entities def entity_detection(detected_text, lang): comprehend = boto3.client("comprehend") # convert and handle string here # do string handling detect_ent_response = comprehend.batch_detect_entities( TextList=detected_text, LanguageCode=lang) # To fold detected entities and entity types ents = [] types = [] # Get detected entities and types from the response returned by Comprehend for i in detect_ent_response['ResultList']: if len(i['Entities']) == 0: ents.append("N/A") types.append("N/A") else: sentence_ents = [] sentence_types = [] for entities in i['Entities']: sentence_ents.append(entities['Text']) sentence_types.append(entities['Type']) ents.append(sentence_ents) types.append(sentence_types) return ents, types
  3. Escreva o código para realizar a detecção da frase-chave no texto detectado.

    # Detect key phrases def key_phrases_detection(detected_text, lang): comprehend = boto3.client("comprehend") key_phrases = [] detect_phrases_response = comprehend.batch_detect_key_phrases( TextList=detected_text, LanguageCode=lang) for i in detect_phrases_response['ResultList']: if len(i['KeyPhrases']) == 0: key_phrases.append("N/A") else: phrases = [] for phrase in i['KeyPhrases']: phrases.append(phrase['Text']) key_phrases.append(phrases) return key_phrases

    Você precisa criar uma função que invoque todo o código que você criou até agora. A função usará a DocumentProcessor classe que você criou em seu DetectAnalyzeFileAsync.py arquivo e, em seguida, salvará o texto detectado em uma variável para entrada nas três funções que você escreveu anteriormente usando o Amazon Comprehend. A função também precisará construir um dataframe Pandas, no qual o texto detectado e os dados de análise serão inseridos. Finalmente, o dataframe do Pandas será salvo como um arquivo CSV.

  4. Escreva o código para processar seus documentos de entrada com o Textract e passe o texto detectado para o Comprehend.

    def process_document(roleArn, bucket, document, region_name): # Create analyzer class from DocumentProcessor, create a topic and queue, use Textract to get text, # then delete topica and queue analyzer = DocumentProcessor(roleArn, bucket, document, region_name) analyzer.CreateTopicandQueue() extracted_text = analyzer.ProcessDocument() analyzer.DeleteTopicandQueue() # detect dominant language comprehend = boto3.client("comprehend") response = comprehend.detect_dominant_language(Text=str(extracted_text[:10])) print(response) print(type(response)) lang = "" for i in response['Languages']: lang = i['LanguageCode'] print(lang) # or you can enter language code below # lang = "en" print("Lines in detected text:" + str(len(extracted_text))) sliced_list = [] start = 0 end = 24 while end < len(extracted_text): sliced_list.append(extracted_text[start:end]) start += 25 end += 25 print(sliced_list) # Create lists to hold analytics data, these will be turned into columns all_sents = [] all_scores = [] all_ents = [] all_types = [] all_key_phrases = [] all_pos_ratings = [] all_neg_ratings = [] all_neutral_ratings = [] all_mixed_ratings = [] # For every slice, get sentiment analysis, entity detection and key phrases, append results to lists for slice in sliced_list: slice_labels, pos_ratings, neg_ratings, neutral_ratings, mixed_ratings = sentiment_analysis(slice, lang) all_sents.append(slice_labels) all_pos_ratings.append(pos_ratings) all_neg_ratings.append(neg_ratings) all_neutral_ratings.append(neutral_ratings) all_mixed_ratings.append(mixed_ratings) slice_ents, slice_types = entity_detection(slice, lang) all_ents.append(slice_ents) all_types.append(slice_types) key_phrases = key_phrases_detection(slice, lang) all_key_phrases.append(key_phrases) # List comprehension to flatten multiple lists into a single list extracted_text = [line for sublist in sliced_list for line in sublist] all_sents = [sent for sublist in all_sents for sent in sublist] all_scores = [score for sublist in all_scores for score in sublist] all_ents = [ents for sublist in all_ents for ents in sublist] all_types = [types for sublist in all_types for types in sublist] all_key_phrases = [kp for sublist in all_key_phrases for kp in sublist] all_mixed_ratings = [kp for sublist in all_mixed_ratings for kp in sublist] all_pos_ratings = [kp for sublist in all_pos_ratings for kp in sublist] all_neg_ratings = [kp for sublist in all_neg_ratings for kp in sublist] all_neutral_ratings = [kp for sublist in all_neutral_ratings for kp in sublist] print(len(extracted_text)) print(len(all_sents)) print(len(all_ents)) print(len(all_types)) print(len(all_key_phrases)) print("List of Recognized Entities:") # Create dataframe and save as CSV df = pd.DataFrame({'Sentences':extracted_text, 'Sentiment':all_sents, 'SentPosScore':all_pos_ratings, 'SentNegScore':all_neg_ratings, 'SentNeutralScore':all_neutral_ratings, 'SentMixedRatings':all_mixed_ratings, 'Entities':all_ents, 'EntityTypes':all_types,'KeyPhrases:':all_key_phrases}) analysis_results = str(document.replace(".","_") + "_" + "analysis" + ".csv") df.to_csv(analysis_results, index=False) print(df) print("Data written to file!") return extracted_text, analysis_results
  5. Escreva o código para processar seus documentos e fazer o upload dos dados resultantes para o S3. No exemplo de código abaixo, substitua o valor de roleArn pelo ARN da função que você configurou para uso com o Amazon Textract. Substitua o valor region_name de pela região em que sua conta está operando. Por fim, substitua o valor bucket_name pelo nome do bucket do S3 que contém seus documentos.

    def main(): # Initialize S3 client and set RoleArn, region name, and bucket name s3 = boto3.client("s3") roleArn = '' region_name = '' bucket_name = '' # initialize global corpus full_corpus = [] # to hold all docs in bucket docs_list = [] # loop through docs in bucket, get names of all docs s3_resource = boto3.resource("s3") bucket = s3_resource.Bucket(bucket_name) for bucket_object in bucket.objects.all(): docs_list.append(bucket_object.key) print(docs_list) # For all the docs in the bucket, invoke document processing function, # add detected text to corpus of all text in batch docs, # and save CSV of comprehend analysis data and textract detected to S3 for i in docs_list: detected_text, analysis_results = process_document(roleArn, bucket_name, i, region_name) full_corpus.append(detected_text) print("Uploading file: {}".format(str(analysis_results))) name_of_file = str(analysis_results) s3.upload_file(name_of_file, bucket_name, name_of_file) # print the global corpus print(full_corpus) if __name__ == "__main__": main()
  6. Coloque o código do processo na seção em um arquivo Python e execute-o.

Você extraiu texto com sucesso usando o Amazon Textract, enviou o texto para o Amazon Comprehend para análise e depois salvou os resultados em um bucket do Amazon S3.