from .... import logger,fitz,BytesIO,sys from .nlp_Processor import SpacyNLP,NLTKNLP class PDFProcessor: """ PDF文件处理器,用于解析PDF文件并处理每一页的内容。 Attributes: file_content (BytesIO): PDF文件的内容。 document_id (str): 文档的唯一标识符。 max_tokens (int): 处理文本时的最大令牌数限制。 bucket_name (str): 用于存储处理结果的存储桶名称。 KbmService: KbmService对象,用于提供文本处理和存储服务。 Methods: process_pdf(): 解析PDF文件并处理每一页的内容,包括文本和图片。 """ def __init__(self, nlp_type=1): """ 初始化PDF处理器,根据指定的NLP类型选择合适的NLP处理器。 Args: nlp_type (int, optional): 指定NLP处理器的类型。1为SpacyNLP,2为NLTKNLP。默认为1。 """ # self.nlp = SpacyNLP() if nlp_type == 1 else NLTKNLP() if nlp_type == 2 else None self.nlp = SpacyNLP() def get_results(self, file_content, document_id, max_tokens, bucket_name, KbmService): """ 解析PDF文件并处理每一页的内容,包括文本和图片。 Args: file_content (BytesIO): PDF文件的内容。 document_id (str): 文档的ID。 max_tokens (int): 最大令牌数。 bucket_name (str): 存储桶的名称。 KbmService: KbmService对象。 Returns: tuple: 包含处理后的句子列表和页面图片列表的元组。 """ self.file_content = file_content self.document_id = document_id self.max_tokens = max_tokens self.bucket_name = bucket_name self.KbmService = KbmService # 初始化日志信息,表示开始解析PDF sentences = None logger.info("开始解析pdf") processed_pages, current_pages = self._process_pdf() # 解析PDF文件并处理每一页的内容 try: sentences = self._split_sentences(processed_pages,max_tokens) # 将处理后的页面列表分割成句子列表 except Exception as e: logger.error(f"错误{str(e)}") logger.info('PDFProcessor处理完成') return sentences, current_pages def _process_pdf(self): """ 解析PDF文件并处理每一页的内容。 Returns: list: 处理后的页面列表。 """ processed_pages = [] # 初始化处理后的页面列表 current_pages =[] pdf_reader = None try: # 检查文件内容是否为BytesIO对象 if isinstance(self.file_content, BytesIO): # 如果是BytesIO对象,则打开PDF文件 pdf_reader = fitz.open(stream=self.file_content, filetype="pdf") else: # 如果不是BytesIO对象,则抛出ValueError异常 raise ValueError(f"文件内容不是BytesIO对象。类型:{type(self.file_content)}") except Exception as e: # 如果在打开PDF时发生异常,则记录错误日志并返回空列表 logger.error(f"打开PDF失败:{str(e)}") raise ValueError(f"打开PDF失败:{str(e)} {sys._getframe().f_lineno}") # 遍历PDF中的每一页 for page_index in range(len(pdf_reader)): current_page = pdf_reader[page_index] # 获取当前页 page_imag = self._process_page_images(current_page) # 处理页面图片 page_text = self._extract_page_text(current_page, pdf_reader) # 提取当前页的文本内容 processed_pages.append(page_text) # 将当前页的文本内容添加到处理后的页面列表中 current_pages.append(page_imag) pdf_reader.close() return processed_pages,current_pages def _extract_page_text(self, page, pdf_reader): """ 提取PDF页面的文本内容。 Args: page (fitz.Page): 需要提取文本的PDF页面对象。 pdf_reader (fitz.Document): PDF文件的阅读器对象。 Returns: str: 页面的文本内容。 """ page_text = page.get_text() # 获取页面的文本内容 for image_info in page.get_images(): image_xref = image_info[0] # 获取图片的引用 extracted_image = pdf_reader.extract_image(image_xref) # 提取图片 raw_image_data = extracted_image["image"] # 获取图片的raw数据 if isinstance(raw_image_data, bytes): extracted_text = self.KbmService.extract_text_from_image(raw_image_data) # 从图片中提取文本 if extracted_text and len(extracted_text) > 5: page_text += extracted_text return page_text def _process_page_images(self, processed_pages): """ 处理页面图片,渲染页面为图像,保存到MinIO,并记录图像名称。 Args: processed_pages (list): 处理后的页面列表。 Returns: list: 包含页面号和图像名称的元组列表。 """ page_images =[] try: # 遍历处理后的页面列表 page_image = self.KbmService.render_page_to_image(processed_pages) # 保存图像到MinIO,并获取图像名称 image_name = self.KbmService.save_image_to_minio(page_image, self.bucket_name) # 将页面号和图像名称作为元组添加到page_images列表中 page_images.append(image_name) except Exception as e: logger.error(f'错误') # 返回包含所有页面图像信息的列表 return page_images def _split_sentences(self, processed_pages,cmax_tokens=250): """ 使用NLP将处理后的内容分割成句子。 Args: processed_pages (list): 处理后的页面列表。 Returns: list: 包含分割后的句子的列表。 """ # 初始化一个空列表,用于存储分割后的句子 sentence_list = [] # 遍历处理后的页面列表 for page_text in processed_pages: # 使用SNLP模型处理文本, sentence_list.append( self.nlp.split_text_into_chunks(page_text,cmax_tokens)) # 返回包含所有分割后的句子的列表 return sentence_list