把 Word 材料交给 AI 知识库前,先保存“这段文字属于哪一节、表格在什么位置、来自哪个文件”。只先读取所有段落再读取所有表格,会破坏两者在原文中的交错顺序,也可能让检索片段失去上下文。
下面用 python-docx 把主文档中的段落和表格按顺序转成 JSON。示例是人为构造的 Word 文档,已在 Windows、Python 3.11.15、python-docx 1.2.0 环境运行;没有连接在线知识库,也没有验证问答准确率。

先确定输入和记录结构
输入是可编辑的 .docx 文件。本例不接受旧版 .doc,也不会对扫描图片执行 OCR。先复制一份原文件用于解析,并保留原件,避免把资料转换与修改内容混在一起。
Document 官方接口提供 iter_inner_content(),按文档顺序产生 Paragraph 或 Table。程序对两种对象分别记录内容,共用同一个 order;标题段落同时更新 heading_path,后面的正文和表格沿用该路径。
| 字段 | 用途 |
|---|---|
| order | 当前块在主文档迭代序列中的位置,从 0 开始 |
| kind | 区分 heading、paragraph 和 table |
| heading_path | 保留当前一级、二级等标题组成的路径 |
| text / rows | 段落文字或按行排列的表格单元格文字 |
| source_file | 保存来源文件名;接入多文件库时还应补文档唯一 ID |
按样式识别标题,而不是按字号猜
样式文档指出,style.name 用于访问样式,style_id 由 Word 自动生成,不保证跨保存稳定。因此本例明确把 Heading 1 到 Heading 9 映射为标题级别,不依据内部 style_id 识别。
如果你的文档使用自定义样式或显示名称与映射不同,先打印各段落的 paragraph.style.name,把真实名称加入 heading_levels,例如 {"章标题": 1, "节标题": 2}。只有手工放大字号而没有应用标题样式的段落,本例会当普通正文处理。
运行完整的交错顺序示例
在独立目录安装 python -m pip install python-docx==1.2.0。将下面代码保存为 parse_docx.py,执行 python parse_docx.py。它先创建带标题、段落、表格的演示文件,再解析并检查顺序。
from pathlib import Path
import json
from docx import Document
from docx.text.paragraph import Paragraph
sample=Document()
sample.add_heading('演示知识库材料',level=1)
sample.add_paragraph('这是人为构造的文档,用于验证解析顺序。')
sample.add_heading('安装步骤',level=2)
sample.add_paragraph('先建立独立环境,再核对包版本。')
table=sample.add_table(rows=2,cols=2)
table.cell(0,0).text='检查项';table.cell(0,1).text='预期结果'
table.cell(1,0).text='环境';table.cell(1,1).text='版本已记录'
sample.add_paragraph('表格之后继续执行输入检查。')
sample.add_heading('验收方法',level=2)
sample.add_paragraph('保存原文件与解析记录,抽查段落和表格顺序。')
sample.save('sample_knowledge.docx')
def parse_docx(path):
document=Document(path)
heading_levels={f'Heading {level}':level for level in range(1,10)}
headings=[]
result=[]
for order,block in enumerate(document.iter_inner_content()):
if isinstance(block,Paragraph):
text=block.text.strip()
level=heading_levels.get(block.style.name if block.style else '')
if level and text:
headings=[pair for pair in headings if pair[0]<level]
headings.append((level,text))
kind='heading'
else:
kind='paragraph'
if not text:
continue
result.append({'order':order,'kind':kind,'heading_path':[x[1] for x in headings],
'text':text,'source_file':Path(path).name})
else:
result.append({'order':order,'kind':'table','heading_path':[x[1] for x in headings],
'rows':[[cell.text for cell in row.cells] for row in block.rows],
'source_file':Path(path).name})
return result
records=parse_docx('sample_knowledge.docx')
tables=[x for x in records if x['kind']=='table']
assert len(tables)==1
table_pos=records.index(tables[0])
assert records[table_pos-1]['text']=='先建立独立环境,再核对包版本。'
assert records[table_pos+1]['text']=='表格之后继续执行输入检查。'
assert tables[0]['heading_path']==['演示知识库材料','安装步骤']
assert records[-1]['heading_path']==['演示知识库材料','验收方法']
Path('docx_records.json').write_text(json.dumps(records,ensure_ascii=False,indent=2),encoding='utf-8')
print('records:',len(records))
print('table_records:',len(tables))
print('table_between_correct_paragraphs:',True)
print('last_heading_path:',records[-1]['heading_path'])
print('saved: docx_records.json')
本地运行输出
records: 8
table_records: 1
table_between_correct_paragraphs: True
last_heading_path: ['演示知识库材料', '验收方法']
saved: docx_records.json
怎样核对 JSON 确实对应原文
本例输出 8 条记录,其中 1 条是表格。表格前一条为“先建立独立环境,再核对包版本。”,后一条为“表格之后继续执行输入检查。”;表格路径为“演示知识库材料 → 安装步骤”,最后一段路径为“演示知识库材料 → 验收方法”。代码同时用断言检查这些关系,异常时直接停止。
打开 sample_knowledge.docx 与 docx_records.json,按 order 逐条比对标题、段落和表格位置。实际资料至少抽查标题跳级、表格前后说明、关键限制条件和文末段落;记录数正确并不证明内容完整。
改成你自己的 Word 材料
- 保留 parse_docx 函数,删掉前面创建 sample 的演示部分。
- 把调用改为
records = parse_docx('自己的文件.docx'),输出文件也换成对应名称;不要将自己的原件命名为演示输出文件。 - 用真实样式名称补充 heading_levels;没有样式的文件先在副本中规范标题。
- 按 kind 把段落与表格送入后续切分,保留 source_file、文档 ID 和原块位置;如果表格单独切片,把所属标题和表头一起带入。
- 选实际会向知识库提出的问题,确认它所需的句子与表格信息都还在转换结果中,再进行向量化。
哪些情况要另加解析规则
本例只遍历主文档层的段落和表格,不保证完整覆盖页眉页脚、文本框、修订记录、图片、嵌套表格或合并单元格的语义。合并单元格在按 row.cells 遍历时可能重复出现,必须对照原表处理,不能直接把重复文字当多条独立事实。
出现“原文有内容、JSON 没有”的情况,先确认文字是否在图片、文本框或修订区域,再选择相应处理方式。不要让模型补写漏掉的数字或条件。正文文字成功读取,也不意味着图中的尺寸、公式或流程已被读取。
标题不连续,会不会报错?
本例允许从一级直接跳到三级,并保留实际出现的路径,不会补造不存在的二级标题。如果下游要求固定层数,应单独记录缺层情况;不要凭空添加一个标题来让结构看起来完整。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/31894.html