如何用Python将含特定结构化数据的doc/docx文件转为JSON?
最简Python方案提取Word文档中的结构化数据
嘿,这个需求其实挺 straightforward 的,不用自己从零啃Word的二进制格式,直接靠成熟工具库搞定文本提取,再用正则抓结构化数据就行,步骤超清晰:
第一步:安装必备库
- 处理
.docx文件:用python-docx,轻量且专门针对docx格式,没有冗余依赖:pip install python-docx - 处理
.doc旧格式:跨平台场景推荐textract(它会自动调用底层工具提取纯文本),Windows用户也可以用pywin32调用本地Word,但textract的通用性更强:
(注:textract在Linux/macOS可能需要额外装系统依赖,比如处理doc要装pip install textractantiword,Ubuntu可以用sudo apt install antiword搞定)
第二步:核心代码实现
思路就是:遍历目标文件夹里的所有doc/docx文件 → 提取纯文本 → 用正则匹配每一条结构化数据 → 整理成字典/列表(方便后续存成CSV/Excel)
import os import re from docx import Document import textract # 定义匹配数据的正则表达式,适配你给出的格式,加\s*兼容可能的空格 pattern = re.compile(r'Name:\s*(\w+),\s*Place:\s*(\w+),\s*Country:\s*(\w+),\s*PHONE NO.:\s*(\d+)') def extract_word_data(file_path): # 根据文件后缀提取文本 if file_path.endswith('.docx'): doc = Document(file_path) text = '\n'.join([para.text for para in doc.paragraphs]) elif file_path.endswith('.doc'): # 用textract提取doc文本并转成utf-8编码 text = textract.process(file_path).decode('utf-8') else: return [] # 匹配所有符合格式的数据条目 matches = pattern.findall(text) # 转换成易读的结构化字典列表 result = [ { 'Name': match[0], 'Place': match[1], 'Country': match[2], 'Phone': match[3] } for match in matches ] return result # 遍历指定文件夹下的所有doc/docx文件 target_folder = './your_word_files' # 替换成你的实际文件夹路径 all_data = [] for filename in os.listdir(target_folder): if filename.endswith(('.doc', '.docx')): file_path = os.path.join(target_folder, filename) data = extract_word_data(file_path) all_data.extend(data) # 输出结果,或者直接存成CSV print(all_data) # 如果要导出成CSV文件,取消下面的注释: # import csv # with open('output_contacts.csv', 'w', newline='', encoding='utf-8') as f: # writer = csv.DictWriter(f, fieldnames=['Name', 'Place', 'Country', 'Phone']) # writer.writeheader() # writer.writerows(all_data)
为啥这是最简方案?
- 完全不用手动解析Word的复杂格式,全靠成熟库搞定文本提取,减少出错概率
- 正则表达式精准匹配你给出的结构化格式,一行就能抓出所有目标数据
- 代码结构清晰,只要替换文件夹路径就能直接跑,扩展性也强(比如要加新字段,改正则就行)
如果你的Word文件里的格式有微小变动(比如字段顺序调整、有换行),只需要微调正则表达式就能适配,比如允许字段间换行的版本:
pattern = re.compile(r'Name:\s*(\w+),?\s*(?:Place:\s*(\w+),?\s*)?(?:Country:\s*(\w+),?\s*)?(?:PHONE NO.:\s*(\d+))?', re.DOTALL)
内容的提问来源于stack exchange,提问作者Rajat




