共计 3028 个字符,预计需要花费 8 分钟才能阅读完成。
理解 Docx 的底层结构
在开始解析之前,我们需要先了解.docx 文件的本质。实际上,一个.docx 文件是一个 ZIP 压缩包,里面包含多个 XML 文件和资源文件。当你解压一个.docx 文件时,会发现以下关键组成部分:

word/document.xml:存储文档的主要内容word/styles.xml:包含文档的所有样式定义word/numbering.xml:列表编号信息word/footnotes.xml:脚注内容word/headerX.xml和word/footerX.xml:页眉页脚word/media/:存放所有嵌入的图片
解析方式对比
- 直接解析 XML
- 优点:完全控制,可以访问所有细节
-
缺点:代码复杂,需要处理大量 XML 命名空间
-
使用 python-docx 库
- 优点:API 友好,快速上手
- 缺点:某些高级特性支持有限
完整代码示例
基础环境设置
# 安装必要库
# pip install python-docx anthropic
from typing import List, Dict, Optional
from docx import Document
import zipfile
import xml.etree.ElementTree as ET
from anthropic import Anthropic
提取带格式文本
def extract_formatted_text(doc_path: str) -> List[Dict]:
"""提取文档中所有段落及其格式信息"""
doc = Document(doc_path)
results = []
for paragraph in doc.paragraphs:
text = paragraph.text
formats = []
# 检查运行 (run) 级别的格式
for run in paragraph.runs:
run_format = {
'text': run.text,
'bold': run.bold,
'italic': run.italic,
'underline': run.underline,
'font': run.font.name
}
formats.append(run_format)
results.append({
'paragraph_text': text,
'formats': formats,
'style': paragraph.style.name
})
return results
解析嵌套表格
def extract_nested_tables(doc_path: str) -> List[List[List[str]]]:
"""提取文档中所有表格数据,支持嵌套表格"""
doc = Document(doc_path)
tables_data = []
for table in doc.tables:
table_data = []
for row in table.rows:
row_data = []
for cell in row.cells:
# 处理单元格中的嵌套表格
if cell.tables:
nested_table = extract_nested_tables_from_cell(cell)
row_data.append(nested_table)
else:
row_data.append(cell.text)
table_data.append(row_data)
tables_data.append(table_data)
return tables_data
集成 Claude API 进行内容分析
class DocxAnalyzer:
def __init__(self, api_key: str):
self.client = Anthropic(api_key=api_key)
self.chunk_size = 10000 # Claude 的上下文窗口限制
def analyze_with_claude(self, text: str) -> str:
"""使用 Claude 分析文本内容"""
prompt = f""" 请分析以下文档内容,提取关键信息并总结:{text}
"""
response = self.client.completions.create(
model="claude-2",
prompt=prompt,
max_tokens_to_sample=1000
)
return response.completion
def process_large_doc(self, doc_path: str) -> List[str]:
"""分块处理大文档"""
doc = Document(doc_path)
full_text = "\n".join([p.text for p in doc.paragraphs])
chunks = [full_text[i:i+self.chunk_size]
for i in range(0, len(full_text), self.chunk_size)]
return [self.analyze_with_claude(chunk) for chunk in chunks]
性能优化策略
- 内存管理
- 使用生成器而非列表存储中间结果
-
对于超大文档,考虑流式处理
-
异步处理
import asyncio async def async_analyze_chunk(chunk: str, analyzer: DocxAnalyzer): return await analyzer.analyze_with_claude(chunk) async def process_doc_async(doc_path: str): analyzer = DocxAnalyzer(API_KEY) chunks = analyzer.get_chunks(doc_path) tasks = [async_analyze_chunk(chunk, analyzer) for chunk in chunks] return await asyncio.gather(*tasks) -
错误重试机制
from tenacity import retry, stop_after_attempt, wait_exponential @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) def safe_analyze(text: str) -> str: try: return analyzer.analyze_with_claude(text) except Exception as e: print(f"分析失败: {e}") raise
生产环境注意事项
- 加密文档处理
- 检测文档是否加密:尝试用 zipfile 打开
-
使用 olefile 或 msoffcrypto-tool 处理加密文档
-
特殊字符转义
- XML 特殊字符(<, >, & 等)需要正确处理
-
使用 xml.sax.saxutils.escape 进行转义
-
版本兼容性
- 测试不同 Office 版本生成的.docx
- 特别注意 2007 版与新版之间的差异
开放式问题
-
增量解析:当文档发生部分变更时,如何只重新解析变更的部分?
-
公式提取:对于文档中的复杂数学公式,除了转换为图片,是否有更好的提取和分析方法?
-
版本对比:如何高效地比较两个版本文档之间的差异,并生成有意义的变更摘要?
这个方案结合了 python-docx 的易用性和 Claude API 的强大分析能力,能够处理大多数复杂的 Docx 文档解析需求。在实际应用中,你可能还需要根据具体场景调整分块策略和提示词设计。
正文完
