

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

# Extraer y enviar texto a AWS Comprehend para su análisis
<a name="textract-to-comprehend"></a>

Amazon Textract le permite incluir la detección y el análisis del texto de los documentos en sus aplicaciones. Con Amazon Textract, puede extraer texto de una variedad de tipos de documentos diferentes mediante el procesamiento de documentos sincrónico y asincrónico. A continuación, el texto extraído puede guardarse en un archivo o base de datos, o enviarse a otro AWS servicio para su posterior procesamiento. 

En este tutorial llevarás a cabo un flujo de trabajo común de principio a fin. Este flujo de trabajo implica:
+ Procesamiento de numerosos documentos de entrada con Amazon Textract
+ Proporcionar el texto extraído a Amazon Comprehend para su análisis
+ Guardar el texto analizado y los datos de análisis en un bucket de Amazon Simple Storage Service (S3)

Para este tutorial, utilizará el [AWS SDK ](https://aws.amazon.com/sdk-for-python/) de Python. También puedes consultar el [ GitHub repositorio de ejemplos del SDK de AWS documentación ](https://github.com/awsdocs/aws-doc-sdk-examples) para ver más tutoriales de Python. 

## Requisitos previos
<a name="tutorial-prerequisites"></a>

Antes de empezar este tutorial, tendrás que instalar Python y completar los pasos necesarios para [ configurar el SDK de Python AWS . ](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) Además de esto, asegúrese de que:
+ [Ha creado una cuenta de AWS y un rol de IAM](https://docs.aws.amazon.com/rekognition/latest/dg/setting-up.html)
+ [Has configurado correctamente tus credenciales de AWS acceso ](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)
+ [Creó un bucket de Amazon S3 ](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)
+ [Configuró Amazon Textract para el procesamiento asincrónico](https://docs.aws.amazon.com/en_us/textract/latest/dg/api-async-roles.html), copiando el número de recurso de Amazon (ARN) del rol de IAM que configuró para su uso con Amazon Textract
+ [Ha otorgado acceso a su rol de IAM a Amazon Comprehend ](https://docs.aws.amazon.com/comprehend/latest/dg/security-iam.html#security_iam_access-manage) 
+ Seleccionó algunos documentos con fines de texto extraction/analysis y los cargó en Amazon S3. Asegúrese de que los archivos que seleccione para el análisis tengan los formatos admitidos por Amazon Textract.

## Inicio de la detección asincrónica de textos en documentos
<a name="tutorial-step-1"></a>

Puede extraer el texto de sus documentos y, a continuación, analizar el texto extraído con un servicio como Amazon Comprehend. Textract admite la extracción de texto de documentos de varias páginas mediante operaciones asincrónicas, que son para procesar documentos grandes de varias páginas. El procesamiento asincrónico de un archivo PDF permite a la aplicación completar otras tareas mientras espera a que finalice el proceso. En esta sección se mostrará cómo importar sus documentos desde un bucket de Amazon S3 y proporcionarlos a la operación de detección asincrónica de texto de Textract. 

En este tutorial se presupone que utilizará Amazon S3 para almacenar los archivos de los que desea extraer texto. Empezará por crear una clase y funciones que detecten el texto de los documentos de entrada. Su aplicación tendrá que conectarse al cliente Textract, así como a los clientes Amazon SQS y Amazon SNS para supervisar el estado de finalización del trabajo asincrónico.

1. Comience por escribir el código para crear un tema de Amazon SNS y una cola de Amazon SQS.

   El siguiente ejemplo de código crea una `DocumentProcessor` clase que se conecta a los tres servicios necesarios y, a continuación, crea una cola de Amazon SQS y un tema de Amazon SNS. El tema de Amazon SNS se utiliza para proporcionar información sobre el estado de finalización del trabajo a una cola de Amazon SQS, que se consultará para obtener el estado de finalización de un trabajo. También hay métodos para eliminar la cola de Amazon SQS y el tema de Amazon SNS una vez que el trabajo se haya completado y los recursos ya no sean necesarios.

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

1. Escriba el código para llamar a la `StartDocumentTextDetection` operación y obtener los resultados de la operación.

   La `DocumentProcessor` clase también necesitará métodos para: 
   + Llame a la `StartDocumentTextDetection` operación
   + Consulte un Amazon SQS para ver el estado de finalización del trabajo
   + Recupere los resultados del trabajo una vez que haya terminado de procesarse

   El siguiente código crea los `GetResults` métodos `ProcessDocument` y que llaman `StartDocumentTextDetection` y obtienen el 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
   ```

1. Guarde el código anterior en un archivo llamado`detectFileAsync.py`.

   Este archivo se utiliza en la siguiente sección para gestionar la detección de texto en los documentos de entrada.

## Procesar sus documentos y enviar el texto a Comprehend
<a name="tutorial-step-2"></a>

Su aplicación utilizará la clase que creó en la sección siguiente para:
+ leer los documentos de su bucket de Amazon S3
+ extraiga el texto de esos documentos
+ envíe el texto a Amazon Comprehend para su análisis

Empieza por crear algunas funciones que utilizan Amazon Comprehend para analizar el texto detectado en los documentos de entrada. Un tipo común de análisis de texto es el análisis de sentimientos, cuyo objetivo es captar el efecto de una afirmación (ya sea positiva, negativa o neutra). También puede detectar entidades y frases clave en los datos.

El siguiente código recoge el texto detectado e invoca la `BatchDetectSentiment` operación de Amazon Comprehend para llevar a cabo un análisis de opiniones.

1. Escribe el código para realizar un análisis de opinión sobre el 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
   ```

   Es posible que también desees realizar otras operaciones de análisis, como la detección de entidades o frases clave, en el texto detectado. Puede escribir las funciones para llevar a cabo estas operaciones de análisis en el texto, tal y como hizo con la operación de análisis de opiniones en curso.

1. Escribe el código para llevar a cabo la detección de entidades en el 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
   ```

1.  Escribe el código para detectar frases clave en el 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
   ```

   Debes crear una función que invoque todo el código que has creado hasta ahora. La función utilizará la `DocumentProcessor` clase que creó en su `DetectAnalyzeFileAsync.py` archivo y, a continuación, guardará el texto detectado en una variable para introducirlo en las tres funciones que utilizó Amazon Comprehend y que escribió anteriormente. La función también necesitará crear un marco de datos de Pandas, en el que se insertarán el texto y los datos de análisis detectados. Finalmente, el marco de datos de Pandas se guardará como un archivo CSV.

1. Escribe el código para procesar tus documentos de entrada con Textract y pasa el texto detectado a 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
   ```

1. Escriba el código para procesar sus documentos y cargue los datos resultantes en S3. En el ejemplo de código que aparece a continuación, sustituya el valor de `roleArn` por el ARN del rol que configuró para usarlo con Amazon Textract. Sustituya el valor de `region_name` por la región en la que opera su cuenta. Por último, reemplaza el valor `bucket_name` por el nombre del bucket de S3 que contiene tus 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()
   ```

1. Coloque el código de procedimiento de la sección en un archivo de Python y ejecútelo. 

Ha extraído correctamente el texto con Amazon Textract, lo ha enviado a Amazon Comprehend para su análisis y, a continuación, ha guardado los resultados en un bucket de Amazon S3.