import json import docx import re import os from PyPDF2 import PdfReader from flask_app.main.截取pdf import clean_page_content,extract_common_header def extract_text_from_docx(file_path): doc = docx.Document(file_path) return '\n'.join([para.text for para in doc.paragraphs]) def extract_text_from_pdf(file_path, start_word, end_pattern): # 从PDF文件中提取文本 common_header = extract_common_header(file_path) pdf_document = PdfReader(file_path) all_pages_text = [] start_index = None # 处理所有页面 for i, page in enumerate(pdf_document.pages): page_text = page.extract_text() if page.extract_text() else "" cleaned_text = clean_page_content(page_text, common_header) # 在第一页查找开始位置 if i == 0 and start_index is None: start_match = re.search(start_word, cleaned_text, re.MULTILINE) if start_match: start_index = start_match.start() cleaned_text = cleaned_text[start_index:] # 在最后一页查找结束位置 if i == len(pdf_document.pages) - 1: for pattern in end_pattern: matches = list(re.finditer(pattern, cleaned_text, re.MULTILINE)) if matches: end_index = matches[-1].start() cleaned_text = cleaned_text[:end_index] break all_pages_text.append(cleaned_text) # 合并所有页面的文本 full_text = "\n".join(all_pages_text) # print(full_text) return full_text def compare_headings(current, new): # 使用过滤来确保只处理非空且为数字的部分 current_nums = [int(num) for num in current.split('.') if num.isdigit()] new_nums = [int(num) for num in new.split('.') if num.isdigit()] # 比较数字序列以确定标题的层次关系 for c, n in zip(current_nums, new_nums): if n > c: return True elif n < c: return False # 如果新标题有更多层次,认为是新的子章节 return len(new_nums) > len(current_nums) def should_add_newline(content, keywords, max_length=20): content_str = ''.join(content).strip() return any(keyword in content_str for keyword in keywords) or len(content_str) <= max_length def handle_content_append(current_content, line_content, append_newline, keywords): if append_newline: if should_add_newline(current_content, keywords): current_content.append('\n') # 添加换行符 append_newline = False current_content.append(line_content) return append_newline """ 保存换行符的具体逻辑: 对于二级标题(如 1.1),如果其后的内容包含关键词或内容较短(<=20字符),会在内容前添加一个换行符。 这个换行符会被保留在 current_content 列表中。 当处理下一个标题时,之前的内容(包括可能存在的换行符)会被合并并保存到 data 字典中。 """ #提取json主函数 def parse_text_by_heading(text): keywords = ['包含', '以下'] data = {} current_key = None current_content = [] append_newline = False lines = text.split('\n') #['一、说明', '1.适用范围', '招标文件仅适用于第一章“投标邀请书”中所述项目的货物、工程及服务的采购。'] for i, line in enumerate(lines): #由于本身就是按行读取处理,因此保存的时候不带'\n' line_stripped = line.strip() # 匹配中文数字标题,包括带括号和不带括号的情况 pattern_title = re.compile(r'^\s*(?:[((]\s*[一二三四五六七八九十]\s*[))]\s*|[一二三四五六七八九十]\s*、\s*)') # 用于提取中文数字部分 pattern_key = re.compile(r'[一二三四五六七八九十]') # 用于提取标题后的内容部分 pattern_value = re.compile(r'[^\s、))]+') chinese_match = pattern_title.match(line_stripped) # 匹配是否为标题 if chinese_match: # 匹配到标题行,先提取中文数字部分 chinese_key_match = pattern_key.search(line_stripped) # 提取中文数字后的内容部分 chinese_value_match = pattern_value.search( line_stripped[chinese_key_match.end():]) if chinese_key_match else None if chinese_key_match and chinese_value_match: chinese_key = chinese_key_match.group() # 匹配到的中文数字,如 "一" chinese_value = chinese_value_match.group() # 匹配到的标题内容,如 "招标文件" # 将提取的标题和内容存储到字典中 if chinese_key: data[chinese_key] = chinese_value current_key = None # 重置当前key current_content = [] # 清空当前内容 continue # 新增:匹配阿拉伯数字开头后跟顿号的情况,如 "7、竞争性磋商采购文件的修改" arabic_match = re.match(r'^(\d+、)\s*(.+)$', line_stripped) if arabic_match: arabic_key, arabic_value = arabic_match.groups() arabic_key = arabic_key.replace('、', '.') # 将顿号替换为点号 if current_key is not None: content_string = ''.join(current_content).strip() data[current_key] = content_string.replace(' ', '') current_key = arabic_key current_content = [arabic_value] append_newline = True continue # 匹配形如 '1.1'、'2.2.3' 等至少包含一个点的标题,并确保其前后没有字母或括号 match = re.match(r'^(?