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.
Extracción y envío de texto a AWS Comprehend para su análisis
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 distintos tipos de documentos mediante el procesamiento de documentos sincrónico y asíncrono. Luego, el texto extraído se puede guardar en un archivo o base de datos, o se puede enviar a otro AWS servicio para su posterior procesamiento.
En este tutorial, llevará a cabo un flujo de trabajo común de principio a fin. Este flujo de trabajo incluye:
-
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ás el AWS SDK para Python
Requisitos previos
Antes de comenzar este tutorial, tendrás que instalar Python y completar los pasos necesarios para configurar el AWS SDK de Python
-
Has configurado correctamente tus credenciales de AWS acceso
-
Configuró Amazon Textract para el procesamiento asíncrono, copiando el número de recurso de Amazon (ARN) de la función de IAM que configuró para su uso con Amazon Textract
-
Se le concedió a su función de IAM acceso a Amazon Comprehend
-
Seleccionó algunos documentos con fines de texto extraction/analysis y cargó el documento en Amazon S3. Asegúrese de que los archivos que seleccione para el análisis sean de los formatos compatibles con Amazon Textract.
Inicio de la detección asíncrona de texto de documentos
Puede extraer el texto de sus documentos y, a continuación, analizarlo con un servicio como Amazon Comprehend. Textract admite la extracción de texto de documentos de varias páginas mediante operaciones asíncronas, que sirven para procesar documentos grandes de varias páginas. Al procesar un archivo PDF de forma asíncrona, la aplicación puede completar otras tareas mientras espera a que se complete el proceso. En esta sección se mostrará cómo importar sus documentos desde un bucket de Amazon S3 y cómo proporcionarlos a la operación de detección de texto asíncrona de Textract.
En este tutorial se asume 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 necesitará conectarse al cliente de Textract, así como a los clientes de Amazon SQS y Amazon SNS para poder monitorizar el estado de finalización del trabajo asincrónico.
-
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
DocumentProcessorclase 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 Amazon SNS se utiliza para proporcionar información sobre el estado de finalización de un 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 se haya completado el trabajo 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) -
Escriba el código para llamar a la
StartDocumentTextDetectionoperación y obtener los resultados de la operación.La
DocumentProcessorclase también necesitará métodos para:-
Llama a la
StartDocumentTextDetectionoperación -
Sondea un Amazon SQS para conocer 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
GetResultsmétodosProcessDocumenty que llamanStartDocumentTextDetectiony 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 -
-
Guarde el código anterior en un archivo llamado
detectFileAsync.py.Utilice este archivo en la siguiente sección para gestionar la detección de texto en los documentos de entrada.
Procesando sus documentos y enviando el texto a Comprehend
Su solicitud utilizará la clase que creó en la sección anterior para:
-
lea documentos de su bucket de Amazon S3
-
extraiga el texto de esos documentos
-
envíe el texto a Amazon Comprehend para su análisis
Comience por crear algunas funciones que utilicen 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 declaración (ya sea positiva, negativa o neutra). También puede realizar la detección de 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 opinión.
-
Escribe el código para realizar un análisis de opinión en 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_scoreEs posible que también desees realizar otras operaciones de análisis, como la detección de entidades o la detección de frases clave, en el texto detectado. Puede escribir las funciones necesarias para llevar a cabo estas operaciones de análisis en el texto, igual que hizo con la operación de análisis de opiniones en curso.
-
Escribe el código para realizar 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 -
Escribe el código para realizar la detección de 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_phrasesDebes crear una función que invoque todo el código que has creado hasta ahora. La función utilizará la
DocumentProcessorclase que creaste en tuDetectAnalyzeFileAsync.pyarchivo y, a continuación, guardará el texto detectado en una variable para introducirlo en las tres funciones que utilizaste Amazon Comprehend que escribiste anteriormente. La función también necesitará construir un marco de datos de Pandas, en el que se insertarán el texto detectado y los datos de análisis. Por último, el marco de datos de Pandas se guardará como un archivo CSV. -
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 -
Escribe el código para procesar tus documentos y carga los datos resultantes en S3. En el ejemplo de código que aparece a continuación, sustituya el valor de
roleArnpor el ARN del rol que configuró para usarlo con Amazon Textract. Sustituya el valor porregion_namela región en la que opera su cuenta. Por último, sustituya el valorbucket_namepor el nombre del depósito de S3 que contiene sus 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() -
Coloque el código de procedimiento de la sección en un archivo 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.