Cursor实战案例-办公提效-74-企业级文档解析:用Python-docx+正则抽取Word合同敏感字段并脱敏
1. 合同批量处理为什么总在“人肉翻页”里打转企业法务、财务、审计三个部门只要提到“历史合同归档”基本都会露出同一种表情。几百份 Word 合同堆在共享盘里格式五花八门有的甲乙方写在正文段落有的塞进表格有的金额用中文大写、有的用阿拉伯数字还有的合同编号藏在页眉。你要做的不是“读一遍”而是把合同编号、签约主体、金额、身份证号、手机号这些字段抽出来做成一张能筛选、能对账、能审计的台账。问题在于手工摘录的出错率极高。我见过一份 300 份合同的归档任务三个人做了两周最后核对时发现金额错位 17 处、甲乙方张冠李戴 9 处。更麻烦的是合规合同里带身份证号、银行账号、手机号一旦台账在部门间流转敏感信息就跟着扩散。所以真正要解决的不是“能不能读 Word”而是“能不能在本地、批量、可复现地把字段抽出来并且输出前就脱敏”。这篇就围绕这个场景用 Cursor 辅助写一套 Python 脚本基于 python-docx 读取 .docx 合同遍历段落和表格用正则表达式定位甲乙方、金额、身份证号、手机号、合同编号输出前做掩码脱敏最后落成 Excel 台账。脚本骨架可以直接复制正则规则可以按你的合同模板改验证动作也一并给出。适合法务运营、财务共享中心、审计岗以及想用 Cursor 提效但不想把合同传到第三方云解析 API 的同学。2. 前置准备TaoToken 与本地环境怎么配写脚本之前先把两件事定下来模型调用通道和本地依赖。Cursor 本身是编辑器它负责帮你补全和改写代码真正跑批量解析的是本地 Python 进程。如果你在 Cursor 里接的是云端模型做代码补全建议把 API 入口统一到 TaoToken这样模型对话、Coding Plan、API Keys 都在一个控制台里管理切换模型不用改一堆环境变量。TaoToken 的定位是模型调用聚合入口官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。它不替代 Cursor也不替代你的 Python 运行时只是把模型请求收敛到一个可管理的 Key 上。对于合同解析这种“代码要反复调、正则要反复试”的任务用 Coding Plan 做长期编码辅助会比每次临时开对话更省心入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。本地环境按下面配组件版本建议作用Python3.10.x运行时正则和 docx 库兼容性稳python-docx0.8.11解析 .docx 的 OOXML 结构支持表格遍历pandas2.1.0结构化字段并导出 Excelopenpyxl3.1.2pandas 写 xlsx 的引擎Cursor最新版辅助写正则、补全函数、生成测试用例安装命令用 uv 或 pip 都行我习惯 uvuv add python-docx0.8.11 pandas2.1.0 openpyxl3.1.2如果你还没配模型 Key先去控制台建一个地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 然后在 API Keys 页面生成密钥入口 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面写了 base_url 和鉴权头的写法。配好之后Cursor 里做代码补全、让模型帮你解释一段正则都走这个通道。注意合同文件本身不要上传到任何云端解析服务。本文方案全程本地读取模型只用来辅助写代码不接触合同内容。3. 可复制配置解析脚本骨架与正则规则这一节是核心。脚本分四块生成模拟合同方便你无样本也能跑通、文本抽取段落表格、正则匹配、脱敏输出。先给完整骨架再拆正则规则。3.1 文本抽取段落和表格都要遍历python-docx 读 .docx 时doc.paragraphs只给正文段落表格内容在doc.tables里。很多合同的甲乙方、税号、电话恰恰在表格单元格中所以必须两边都抓拼成一个文本块再跑正则。# -*- coding: utf-8 -*- 文件名: contract_parser.py 描述: 解析 Word 合同抽取敏感字段并脱敏输出 Excel 台账 import os import re from docx import Document import pandas as pd def extract_all_text(file_path): 遍历段落与表格返回拼接后的全文 doc Document(file_path) lines [] # 1. 正文段落 for para in doc.paragraphs: text para.text.strip() if text: lines.append(text) # 2. 表格逐行逐单元格 for table in doc.tables: for row in table.rows: for cell in row.cells: cell_text cell.text.strip() if cell_text: lines.append(cell_text) return \n.join(lines)这里有个细节合并单元格在 python-docx 里会被重复读取同一个 cell 对象可能出现在多个 row 中。如果你发现税号被抽了两次可以在拼接前用set去重或者按cell._tc的 id 判重。我一般先不去重让正则用findall取第一个够用。3.2 正则规则配置把字段规则集中管理正则不要散落在代码里集中成一个字典改模板时只动这一块。下面这套规则覆盖合同编号、签约日期、甲乙方、金额、身份证号、手机号、税号。PATTERNS { # 合同编号HT-2026-668899 / 合同编号ABC123 contract_code: r合同编号[:\s]*([A-Za-z0-9\-]{6,30}), # 签约日期2026年06月22日 / 2026-06-22 sign_date: r签约(?:时间|日期)[:\s]*(\d{4}[年\-/]\d{1,2}[月\-/]\d{1,2}日?), # 甲方主体甲方杭州某某科技有限公司 party_a: r甲方(?:委托方)?[:\s]*([^\n\r,。;]{4,40}), # 乙方主体 party_b: r乙方(?:服务方)?[:\s]*([^\n\r,。;]{4,40}), # 金额人民币 500000.00 元 / 总额为 500,000.00 amount: r(?:总额为|合同金额|费用总额|服务费总额)[:\s]*人民币[\s]*([\d,]\.?\d*), # 身份证号18 位末位可能是 X id_card: r\b(\d{17}[\dXx])\b, # 手机号1 开头 11 位 phone: r\b(1[3-9]\d{9})\b, # 纳税人识别号15-20 位字母数字 tax_id: r纳税人识别号[:\s]*([A-Za-z0-9]{15,20}), }金额那条正则里我加了[\d,]因为很多合同写500,000.00带千分位逗号。抽出来之后要replace(,, )再转 float否则float(500,000.00)会报错。3.3 脱敏函数输出前先掩码脱敏要在写 Excel 之前做不能先落盘再处理。掩码规则按字段类型分def mask_value(value, kind): 按字段类型做掩码脱敏 if not value or value Unknown: return value if kind company: # 杭州艾维科技有限公司 - 杭州**有限公司 if len(value) 6: return value[:2] ** value[-4:] return value[:2] ** if kind phone: # 13858888888 - 138****8888 if len(value) 11: return value[:3] **** value[-4:] return value if kind id_card: # 保留前 6 后 4 if len(value) 15: return value[:6] ******** value[-4:] return value if kind tax_id: # 91330106MA2H12345X - 9133**********45X if len(value) 15: return value[:4] ********** value[-3:] return value return value身份证号脱敏保留前 6 位地区码和后 4 位中间 8 位打码这是常见的合规做法。手机号保留前 3 后 4。公司名保留前 2 后 4中间打码既能对账又不暴露全称。3.4 主流程批量扫描目录并导出def parse_contract(file_path): 解析单份合同返回字段字典 text extract_all_text(file_path) result {key: Unknown for key in PATTERNS} for key, pattern in PATTERNS.items(): match re.search(pattern, text) if match: result[key] match.group(1).strip() # 金额去掉千分位逗号 if result[amount] ! Unknown: result[amount] result[amount].replace(,, ) return result def run_batch(input_dir, output_xlsx): 批量解析目录下所有 docx脱敏后写 Excel files [ f for f in os.listdir(input_dir) if f.lower().endswith(.docx) and not f.startswith(~$) ] if not files: print([Warn] 目录下没有可解析的 .docx 文件) return records [] for filename in files: path os.path.join(input_dir, filename) print(f[Parsing] {filename}) try: raw parse_contract(path) except Exception as e: print(f[Error] {filename} 解析失败: {e}) continue records.append({ 文件名: filename, 合同编号: raw[contract_code], 签约日期: raw[sign_date], 合同金额: float(raw[amount]) if raw[amount] ! Unknown else 0.0, 甲方主体: mask_value(raw[party_a], company), 乙方主体: mask_value(raw[party_b], company), 甲方税号: mask_value(raw[tax_id], tax_id), 手机号: mask_value(raw[phone], phone), 身份证号: mask_value(raw[id_card], id_card), }) df pd.DataFrame(records) df.to_excel(output_xlsx, indexFalse, sheet_name合同台账) print(f[Done] 台账已导出: {output_xlsx}) if __name__ __main__: run_batch(./contracts_input, ./contracts_input/audit_summary.xlsx)~$开头的文件是 Word 打开时生成的临时锁文件必须排除否则会抛PackageNotFoundError。4. 验证请求跑通一份模拟合同看结果没有现成合同样本时先用 python-docx 生成一份带表格的模拟合同验证整条链路。from docx import Document from docx.shared import Pt def make_mock_contract(path): doc Document() doc.add_paragraph(技术开发与咨询服务合同) doc.add_paragraph(合同编号HT-2026-668899) doc.add_paragraph(签约时间2026年06月22日) doc.add_paragraph( 本合同项下研发服务费总额为人民币 500,000.00 元。 ) table doc.add_table(rows4, cols2) table.style Table Grid table.cell(0, 0).text 甲方杭州艾维科技有限公司 table.cell(0, 1).text 乙方贵州某某信息技术有限公司 table.cell(1, 0).text 纳税人识别号91330106MA2H12345X table.cell(1, 1).text 纳税人识别号91520382MA6D67890Y table.cell(2, 0).text 联系电话13858888888 table.cell(2, 1).text 联系电话18908519999 table.cell(3, 0).text 身份证号330106199001011234 table.cell(3, 1).text 身份证号520382199202024567 doc.save(path) print(f[Init] 模拟合同已生成: {path}) if __name__ __main__: os.makedirs(./contracts_input, exist_okTrue) make_mock_contract(./contracts_input/mock_001.docx) run_batch(./contracts_input, ./contracts_input/audit_summary.xlsx)运行命令uv run python contract_parser.py预期输出[Init] 模拟合同已生成: ./contracts_input/mock_001.docx [Parsing] mock_001.docx [Done] 台账已导出: ./contracts_input/audit_summary.xlsx打开audit_summary.xlsx你应该看到字段原始值脱敏后合同编号HT-2026-668899不脱敏合同金额500000.00500000.0甲方主体杭州艾维科技有限公司杭州**有限公司甲方税号91330106MA2H12345X9133**********45X手机号13858888888138****8888身份证号330106199001011234330106********1234如果金额列显示为 0.0说明金额正则没匹配上检查合同里金额的写法是不是“总额为人民币”之外的表述把新表述加进PATTERNS[amount]的(?:...)分组里。5. 本篇常见错排查5.1 PackageNotFoundError文件不是真正的 docx报错长这样docx.opc.exceptions.PackageNotFoundError: Package not found at contract.docx原因通常是两种路径写错或者文件其实是 .doc 旧格式被强行改了后缀。python-docx 只认 OOXML 的 zip 结构.doc 是二进制 OLE 格式读不了。解决办法是用 LibreOffice 批量转libreoffice --headless --convert-to docx *.doc转完再跑脚本。另外在批量循环里用 try/except 包住单文件解析避免一份坏文件让整批中断。5.2 表格内容抽不到只遍历了 paragraphs如果你发现甲乙方、税号全是 Unknown但正文里的合同编号能抽到基本是表格没遍历。检查extract_all_text里有没有doc.tables那段。还有一种情况是合同用了文本框text boxpython-docx 默认读不到文本框里的内容需要走 XML 层解析w:txbxContent这个场景较少遇到再单独处理。5.3 正则匹配到多余内容甲乙方抓到整段甲方[:\s]*([^\n\r,。;]{4,40})里我限制了终止字符如果合同写“甲方杭州某某科技有限公司以下简称甲方”会把括号也抓进去。可以在匹配后做一次清洗value re.split(r[(], result[party_a])[0].strip()把括号前的内容截出来。Cursor 里可以让模型帮你根据实际合同样本调这条正则把样本贴进去让它生成更精确的字符集。5.4 金额转 float 报错float(500,000.00)会抛ValueError。前面已经用replace(,, )处理了但如果你合同里金额带“元”字或空格还要再 strip。稳妥写法amount_str re.sub(r[^\d.], , raw[amount]) amount float(amount_str) if amount_str else 0.05.5 脱敏后无法对账脱敏是为了防泄露但财务对账时需要能区分不同主体。公司名保留前 2 后 4 通常够区分如果两家公司前 2 后 4 相同可以改成保留前 3 后 3或者额外加一列哈希值如hashlib.md5(全称.encode()).hexdigest()[:8]用哈希做唯一标识既不可逆又能对账。6. 把脚本接进你的工作流脚本跑通只是第一步。实际落地时我建议把PATTERNS抽成独立的patterns.py不同合同模板配不同规则文件主流程不变。批量任务用concurrent.futures.ThreadPoolExecutor并发解析IO 密集场景能快 3 到 5 倍但注意 Excel 写入要加锁或最后统一写。如果你在 Cursor 里继续迭代这套脚本比如加 OCR 处理扫描件、加银行账号抽取、加合同到期提醒可以把模型调用统一走 TaoToken 的 Coding Plan长期编码场景下比零散开对话更连贯入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。需要临时验证某段正则或让模型解释报错用模型对话页面就行地址 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入细节和鉴权头写法看文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 管理。最后提醒一句生成的台账 xlsx 落盘后记得设只读权限或者直接写进带 RBAC 的数据库。脱敏解决的是“看到什么”权限解决的是“谁能看”两层都要有。

相关新闻

深入理解 /dev/shm:tmpfs 内存文件系统原理、调优与实战排坑

深入理解 /dev/shm:tmpfs 内存文件系统原理、调优与实战排坑

1. 走近 /dev/shm:Linux 里的“隐形内存盘”接触 Linux 时间久了,你会发现系统里有不少“奇怪”的目录,/dev/shm 就是其中之一。第一次注意到它,多半是在执行 df -h 的时候,突然看到一行 tmpfs 挂载在 /dev/shm 上&…

2026/9/29 5:53:10 阅读更多 →
必收藏!大模型评估全攻略:从LLM as a Judge到人工评估的完整指南(TaoToken 统一 Key 配置版)

必收藏!大模型评估全攻略:从LLM as a Judge到人工评估的完整指南(TaoToken 统一 Key 配置版)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/29 5:52:10 阅读更多 →
Spring AI MCP 架构详解:TaoToken 统一 Key 接入与 settings.json 配置骨架

Spring AI MCP 架构详解:TaoToken 统一 Key 接入与 settings.json 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/29 5:52:10 阅读更多 →

最新新闻

脑机接口产业化临界点:技术路线、应用场景与资本逻辑

脑机接口产业化临界点:技术路线、应用场景与资本逻辑

1. 脑机接口的分水岭:从实验室到产业化的临界点过去几年,脑机接口(Brain-Computer Interface, BCI)这个词从脑科学论文里一步步走进了普通人的视野。几年前我和同行聊起BCI,大家讨论的还是电极怎么植入、信号怎么解码这…

2026/9/30 8:44:07 阅读更多 →
Python操作RabbitMQ入门:核心概念与五个实战示例

Python操作RabbitMQ入门:核心概念与五个实战示例

不少后端开发者第一次听说 RabbitMQ,脑子里蹦出来的第一句话往往是:"这玩意儿不就是把一条消息从一堆代码扔到另一堆代码吗?" 方向没错。但等你真正打开官方文档,看到 exchange、binding、routing key、durable、prefe…

2026/9/30 8:44:07 阅读更多 →
Hindsight:基于日志回放的浏览器性能分析开源工具实战

Hindsight:基于日志回放的浏览器性能分析开源工具实战

第一次注意到“hindsight”这个词,是在翻Mozilla的GitHub仓库找性能分析工具的时候。说实话,当时扫到这个名字,第一反应是:这名字起得挺妙。Hindsight直译是“后见之明”,通俗点说就是“回头看清”,用来给一…

2026/9/30 8:44:07 阅读更多 →
TensorFlow工业部署核心:ABI兼容性、SavedModel契约与tf.function编译原理

TensorFlow工业部署核心:ABI兼容性、SavedModel契约与tf.function编译原理

1. 这不是“又一个深度学习框架”——TensorFlow的本质是工程化AI生产流水线 很多人第一次听说TensorFlow,是在2015年谷歌开源它的时候。当时朋友圈刷屏的标题是:“谷歌放出大招!新框架吊打Theano!”——但十年过去,真…

2026/9/30 8:44:07 阅读更多 →
会议录音APP实时转文字有哪些关键技术

会议录音APP实时转文字有哪些关键技术

会议录音APP实时转文字的核心价值,是实现人声与文本的毫秒级同步输出。很多用户在中型会议室、线下讲座场景中,常会遇到远距离收音模糊、多人发言混叠、环境杂音干扰导致的转写错乱、漏字错字等问题。这类使用翻车现象,本质是底层音频处理、A…

2026/9/30 8:44:07 阅读更多 →
深入icoding哈希表create_hash函数的内存与契约解析

深入icoding哈希表create_hash函数的内存与契约解析

1. 这不是“写个哈希表”——而是吃透icoding实验里那个被反复拷贝却没人真懂的hash.h 你有没有在icoding数据结构实验平台里,打开“哈希表创建”这一关,看到 hash.h 头文件里那十几行带注释的代码,心里嘀咕:“这注释写得好像挺…

2026/9/30 8:43:07 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 8:16:59 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/29 8:24:48 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →