Python实现word文档内容智能提取以及合成 python操作word详细操
目录
- 核心思路
- 技术路径
- 实现步骤
- 阶段一:准备职业
- 阶段二:内容提取 (Python 脚本)
- 阶段三:语言风格调整 (可选, Python + LLM API)
- 阶段四:生成目标文档 (Python 脚本)
- 阶段五:人工审阅与精修
- 关于公式处理的挑战与策略
- 拓展资料
怎样从10个左右的docx文档中抽取内容,生成新的文档,抽取内容包括源文档的文字内容、图片、表格、公式等,以及目标文档的样式排版、字体、格式,还有目标文档的语言风格、用词规范、文法习性等等。这一个相当复杂的需求,由于它不仅涉及内容提取,还涉及深度格式化和风格模仿。完全自动化的完美解决方案难度极高,特别是对于复杂的公式和微妙的语言风格。
一个务实的方案是采用 自动化 + 人工辅助 的混合策略。下面内容是详细的思路、技术路径、技巧和步骤:
核心思路
内容提取 (自动化为主): 使用编程方式从源 DOCX 文件中提取所需的核心内容(文字、图片、表格、公式的某种表示)。
样式应用 (自动化): 基于一个定义了目标样式、排版、字体等的 模板文档,将提取的内容插入新文档,并应用模板中定义的样式。
语言风格调整 (自动化辅助 + 人工): 利用大型语言模型 (LLM) 或天然语言处理 (NLP) 技术对提取的文本进行初步的风格、用词和文法调整,接着进行人工审阅和精修。
复杂元素处理 (人工为主): 对于难以自动处理的元素(如复杂公式、特定排版),进行人工调整。
技术路径
主要工具: Python 编程语言
核心库:
- python-docx: 用于读取和写入 DOCX 文件(文本、表格、图片、基本样式应用)。
- (可选) 用于公式处理: 可能需要解析 DOCX 的底层 XML (OOXML),或者寻找专门处理 MathML/OMML 的库(这部分比较困难),或者将公式提取为图片。
- (可选) 用于图片处理: Pillow (PIL Fork) 可能需要用于处理图片。
- (可选) 用于语言风格调整: 调用大型语言模型 API (如 OpenAI GPT 系列、Google Gemini、或其他类似服务)。
辅助工具:
- Microsoft Word: 用于创建模板文档、最终审阅和调整。
- XML 编辑器 (可选): 用于深入分析 DOCX 内部结构(特别是公式)。
实现步骤
阶段一:准备职业
1.创建目标模板文档 (template.docx):
- 在 Word 中创建一个新文档。
- 定义样式: 精心设置所有需要的样式(深入了解 1、深入了解 2、、引用、列表、表格样式等),包括字体、字号、颜色、段落间距、缩进等。确保样式名称清晰易懂(例如 TargetHeading1, TargetBodyText, TargetTableStyle)。
- 设置页面布局: 页边距、纸张大致、页眉页脚等。
- 保存: 将此文档保存为 template.docx。这将是所有新生成文档的基础。
2.明确提取制度:
关键: 你需要非常清楚地定义 哪些 内容需要从每个源文档中提取出来。制度可以基于:
- 特定深入了解: “提取 ‘第三章 技巧’ 下的所有内容”。
- 特定样式: “提取所有应用了 ‘源文档重点’ 样式的内容”。
- 关键词/标记: “提取包含 ‘[EXTRACT]’ 标记的段落”。
- 结构位置: “提取每个文档的第二个表格”。
- 人工指定: (最灵活但最慢) 手动在源文档中标记要提取的内容(例如使用 Word 的批注功能或特定高亮颜色),接着让脚本识别这些标记。
- 文档化制度: 将这些制度清晰地记录下来,以便编写脚本。
3.设置开发环境:
安装 Python。
使用 pip 安装必要的库:
pip install python-docx Pillow requests 如果需要调用 LLM API 可能需要其他库,取决于具体实现
(可选) 获取 LLM API 密钥。
阶段二:内容提取 (Python 脚本)
import osfrom docx import Documentfrom docx.shared import Inches 可能需要导入其他模块,如处理 XML 或调用 API — 配置 —SOURCE_DOCS_DIR = ‘files/transform/docx/source_documents’TARGET_TEMPLATE = ‘files/transform/docx/template.docx’OUTPUT_DOC_PATH = ‘files/transform/docx/generated_document.docx’EXTRACTION_RULES = 示例制度,需要根据你的实际情况修改 ‘source_doc_1.docx’: ‘heading_start’: ‘Chapter 3’, ‘heading_end’: ‘Chapter 4’}, ‘source_doc_2.docx’: ‘style_name’: ‘SourceHighlight’}, … 其他文档的制度} — 辅助函数 (示例) —def should_extract_paragraph(paragraph, rules): 实现基于制度判断段落是否应该提取的逻辑 例如:检查段落文本是否匹配、样式是否匹配等 返回 True 或 False (这部分逻辑需要根据你的具体制度编写) style_name = paragraph.style.name text = paragraph.text.strip() 示例:基于样式的简单制度 if ‘style_name’ in rules and style_name == rules[‘style_name’]: return True 示例:基于起始深入了解的简单制度(需要情形管理) if ‘heading_start’ in rules … (需要更复杂的逻辑来跟踪当前章节) return False 默认不提取def extract_content_from_doc(source_path, rules): “””从单个源文档提取内容””” extracted_elements = [] try: source_doc = Document(source_path) 标记是否处于提取区域(例如,在特定章节之间) in_extraction_zone = False 需要根据制度调整初始情形 for element in source_doc.element.body: 处理不同类型的元素:段落、表格等 if element.tag.endswith(‘p’): 是段落 paragraph = docx.text.paragraph.Paragraph(element, source_doc) — 核心提取逻辑 — 这里需要根据你的 EXTRACTION_RULES 实现复杂的判断逻辑 例如,判断是否遇到起始深入了解,是否遇到结束深入了解,段落样式是否匹配等 这一个简化的示例,实际可能需要更精细的情形管理 if ‘heading_start’ in rules and paragraph.style.name.startswith(‘Heading’) and rules[‘heading_start’] in paragraph.text: in_extraction_zone = True continue 不提取起始深入了解本身?看需求 if ‘heading_end’ in rules and paragraph.style.name.startswith(‘Heading’) and rules[‘heading_end’] in paragraph.text: in_extraction_zone = False continue 到达结束深入了解,停止提取 if in_extraction_zone or should_extract_paragraph(paragraph, rules): 提取文本内容 text_content = paragraph.text 尝试提取基本格式(粗体、斜体) – 比较复杂,可能需要遍历 runs TODO: 提取图片 (需要检查段落中的 inline_shapes 或 runs 中的 drawing) TODO: 提取公式 (极具挑战性,见下文讨论) extracted_elements.append(‘type’: ‘paragraph’, ‘text’: text_content, ‘style’: paragraph.style.name}) 可以携带源样式名供参考 elif element.tag.endswith(‘tbl’): 是表格 table = docx.table.Table(element, source_doc) — 提取表格 — TODO: 实现表格提取逻辑,可能需要检查是否在提取区域内 if in_extraction_zone or table_should_be_extracted(table, rules): table_data = [] for row in table.rows: row_data = [cell.text for cell in row.cells] table_data.append(row_data) extracted_elements.append(‘type’: ‘table’, ‘data’: table_data}) — 处理图片 — 查找段落内的图片 (inline_shapes) paragraph = docx.text.paragraph.Paragraph(element, source_doc) Re-get paragraph object if needed for run in paragraph.runs: if run.element.xpath(‘.//wp:inline | .//wp:anchor’): Check for drawings This part is complex: need to get image data (rId) and relate it back to the actual image part in the docx package. python-docx can extract images, but associating them perfectly with their original position during extraction requires care. Placeholder: image_data = get_image_data(run, source_doc) if image_data: extracted_elements.append(‘type’: ‘image’, ‘data’: image_data, ‘filename’: f’img_len(extracted_elements)}.png’}) pass Placeholder for image extraction logic except Exception as e: print(f”Error processing source_path}: e}”) return extracted_elements — 主流程 —all_extracted_content = []source_files = [f for f in os.listdir(SOURCE_DOCS_DIR) if f.endswith(‘.docx’)]for filename in source_files: source_path = os.path.join(SOURCE_DOCS_DIR, filename) rules = EXTRACTION_RULES.get(filename, }) 获取该文件的提取制度 if rules: 只处理定义了制度的文件 print(f”Extracting from: filename}”) content = extract_content_from_doc(source_path, rules) all_extracted_content.extend(content) else: print(f”Skipping filename}, no rules defined.”)print(f”Total elements extracted: len(all_extracted_content)}”)
阶段三:语言风格调整 (可选, Python + LLM API)
— —import requestsimport json — 配置 LLM —LLM_API_URL = “YOUR_LLM_API_ENDPOINT” e.g., OpenAI API URLLLM_API_KEY = “YOUR_LLM_API_KEY”LLM_PROMPT_TEMPLATE = “””请根据下面内容要求,改写这段文字:目标语言风格:[在此处详细描述,例如:正式、客观、简洁]用词规范:[在此处列出规范,例如:使用“用户”而非“客户”,避免使用缩写]文法习性:[在此处描述,例如:多使用主动语态,句子长度适中]目标受众:[描述目标读者]原文:”text}”改写后的文字:”””def adapt_text_style(text): “””使用 LLM API 调整文本风格””” if not text.strip(): return text 跳过空文本 prompt = LLM_PROMPT_TEMPLATE.format(text=text) headers = “Authorization”: f”Bearer LLM_API_KEY}”, “Content-Type”: “application/json”, } data = “model”: “gpt-4”, 或你使用的模型 “prompt”: prompt, “max_tokens”: 1024, 根据需要调整 “temperature”: 0.5, 控制创新性,较低值更保守 } try: response = requests.post(LLM_API_URL, headers=headers, json=data) response.raise_for_status() 检查 HTTP 错误 result = response.json() 解析 LLM 返回的结局,注意不同 API 的格式可能不同 rewritten_text = result[‘choices’][0][‘text’].strip() 示例路径 print(f”Original: text[:50]}… | Rewritten: rewritten_text[:50]}…”) return rewritten_text except requests.exceptions.RequestException as e: print(f”Error calling LLM API: e}”) return text 出错时返回原文 except (KeyError, IndexError) as e: print(f”Error parsing LLM response: e} – Response: response.text}”) return text 出错时返回原文 — 应用风格调整 —adjusted_content = []for element in all_extracted_content: if element[‘type’] == ‘paragraph’: — 调用 LLM API — adjusted_text = adapt_text_style(element[‘text’]) element[‘text’] = adjusted_text 更新文本 — 或者先不调用,等生成后再处理 — adjusted_content.append(element) elif element[‘type’] == ‘table’: 表格内容也可以逐个单元格处理,但可能效果不佳或成本高 更好的技巧可能是将表格内容整理成文本描述给 LLM,或者人工处理 adjusted_content.append(element) elif element[‘type’] == ‘image’: 图片无法直接处理 adjusted_content.append(element) 处理其他类型… — (接续到下一阶段:文档生成) —
阶段四:生成目标文档 (Python 脚本)
— (续上) — — 创建目标文档 (基于模板) —try: target_doc = Document(TARGET_TEMPLATE)except Exception as e: print(f”Error loading template TARGET_TEMPLATE}: e}”) 可以考虑创建一个空文档作为后备 target_doc = Document() exit() — 填充内容并应用样式 —for element in adjusted_content: 使用调整后的内容,或者原始提取内容 if element[‘type’] == ‘paragraph’: text = element[‘text’] — 核心:应用模板中定义的样式 — 简单方式:所有段落应用默认样式 target_doc.add_paragraph(text, style=’TargetBodyText’) 假设模板中有此样式 复杂方式:根据源文档信息或内容判断应用哪个目标样式 示例:如果源样式是 Heading 1,应用 TargetHeading1 source_style = element.get(‘style’, ”) 获取源样式名(如果提取时保存了) if source_style.startswith(‘Heading 1′): target_doc.add_paragraph(text, style=’TargetHeading1’) 假设模板中有此样式 elif source_style.startswith(‘Heading 2′): target_doc.add_paragraph(text, style=’TargetHeading2′) … 其他样式映射制度 else: target_doc.add_paragraph(text, style=’TargetBodyText’) 默认样式 elif element[‘type’] == ‘table’: table_data = element[‘data’] if table_data: 创建表格 num_rows = len(table_data) num_cols = len(table_data[0]) if num_rows > 0 else 0 if num_rows > 0 and num_cols > 0: — 应用模板中定义的表格样式 — table = target_doc.add_table(rows=num_rows, cols=num_cols, style=’TargetTableStyle’) 假设模板中有此表格样式 填充数据 for i, row_data in enumerate(table_data): for j, cell_text in enumerate(row_data): 防止列数不匹配错误 if j < len(table.rows[i].cells): table.rows[i].cells[j].text = cell_text 可以添加更多表格格式化代码,如设置列宽等 elif element[‘type’] == ‘image’: — 添加图片 — image_data = element[‘data’] image_filename = element[‘filename’] 需要将 image_data 保存为临时文件或使用 BytesIO from io import BytesIO image_stream = BytesIO(image_data) try: target_doc.add_picture(image_stream, width=Inches(4.0)) 调整宽度 except Exception as e: print(f”Error adding image image_filename}: e}”) pass Placeholder for image insertion — 处理公式 (挑战) — 如果公式被提取为图片: elif element[‘type’] == ‘formula_image’: 添加图片… 如果公式被提取为 MathML/OMML (XML 字符串): elif element[‘type’] == ‘formula_mathml’: 使用 python-docx 直接插入 MathML 很困难 可能需要直接操作 OOXML (非常复杂) 或者,在段落中插入一个占位符 “[FORMULA]”,接着手动替换 target_doc.add_paragraph(f”[FORMULA: element[‘id’]}]”, style=’TargetBodyText’) 如果公式被提取为纯文本近似值: elif element[‘type’] == ‘formula_text’: target_doc.add_paragraph(element[‘text’], style=’FormulaStyle’) 可能需要独特样式 — 保存最终文档 —try: target_doc.save(OUTPUT_DOC_PATH) print(f”Document successfully generated: OUTPUT_DOC_PATH}”)except Exception as e: print(f”Error saving document: e}”)
阶段五:人工审阅与精修
1.打开生成的文档 (generated_document.docx)。
2.检查整体结构和内容完整性: 是否所有需要的内容都被提取并放置在正确的位置?
3.检查样式和格式:
- 所有文本是否应用了正确的模板样式?
- 字体、字号、间距是否符合要求?
- 表格样式是否正确?列宽、对齐是否需要调整?
- 图片位置和大致是否合适?
4.检查语言风格和规范:
- 通读文本,检查语气、用词是否符合目标要求。
- 修正 LLM 可能产生的错误或不天然的表达。
- 确保术语统一。
- 进行拼写和语法检查。
5.处理复杂元素:
公式: 这是最可能需要手动操作的地方。如果脚本插入了占位符,你需要手动将源文档中的公式复制粘贴过来,或者使用 Word 的公式编辑器重新创建它们。确保公式的编号和引用正确。
独特排版: 检查是否有需要独特布局(如图文混排、分栏等)的地方,并手动调整。
6.最终定稿: 保存修改后的文档。
关于公式处理的挑战与策略
难点: DOCX 中的公式通常使用 OMML (Office Math Markup Language) 存储,嵌套在复杂的 XML 结构中。python-docx 对此支持有限。
策略:
- 提取为图片 (最可行): 尝试在提取阶段将公式渲染或截图为图片。这会丢失编辑能力,但能保证视觉效果。实现起来也有难度,可能需要借助其他工具或库(如 docx2python 库可能提供一些帮助,或者需要分析 OOXML 找到图片表示)。
- 提取为 MathML/OMML (复杂): 解析 OOXML,提取公式的 XML 片段。但 python-docx 无法直接将这些 XML 重新插入并渲染为公式。需要非常底层的 OOXML 操作。
- 提取为近似文本 (简单但损失精度): python-docx 读取包含公式的段落 text 属性时,有时会得到一个纯文本的近似表示。这对于简单公式可能够用,但复杂公式会完全失真。
- 手动处理 (最可靠): 在脚本中识别出公式位置,插入占位符,接着在人工审阅阶段手动复制/创建公式。
拓展资料
这一个多阶段、结合自动化和人工的经过。
自动化强项: 重复性的内容提取、基于模板的样式应用、初步的文本风格转换(使用 LLM)。
人工介入点: 定义精确的提取制度、处理复杂公式、精调语言风格和术语、最终的格式微调和质量检查。
投入时刻最多的部分将是 编写和调试提取逻辑 以及 最终的人工审阅和修正。务必从少量文档和简单制度开始,逐步迭代和完善你的脚本。
以上就是Python实现word文档内容智能提取以及合成的详细内容,更多关于Python word文档内容提取与合成的资料请关注风君子博客其它相关文章!
无论兄弟们可能感兴趣的文章:
- Python实现批量提取word文件中文本框内容
- Python实现提取Word文档中的文本和图片
- Python提取Word中图片的实现步骤
- python提取word文件中的所有图片
- python批量提取word内信息
- Python利用模板生成Word的三种技巧
- PythonWord实现批量替换文本并生成副本
- Python快速生成定制化的Word(docx)文档