首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >程序员转型练手项目:合同关键信息抽取器(完整代码 + 演示)

程序员转型练手项目:合同关键信息抽取器(完整代码 + 演示)

原创
作者头像
三合卓学
发布于 2026-11-03 13:49:52
发布于 2026-11-03 13:49:52
780
举报

转型 FDE 的路线里,"攒三个可展示的项目"是最难启动的一步。本文给出一个能现场跑通的第一项目:从合同文本中批量抽取甲方、金额、期限、违约责任条款,输出结构化 CSV。场景真实(律所、法务、采购都有这个痛点)、技术门槛适中(正则规则 + 可插拔的模型兜底)、演示效果直观(一堆 txt 进去,一张表出来)。全程只用标准库。

一、目标与边界

输入:一个目录下的若干 .txt 合同文本(真实场景中是 PDF/Word,文末给出扩展说明)。输出:CSV,每行一份合同,列为各抽取字段。边界:规则抽取只覆盖写法规范的条款,对不规范文本返回空值并记入 miss 列,由后续的人工复核或模型兜底处理——知道规则系统在哪里失效,比假装它全能重要。

二、完整代码 extractor.py

代码语言:javascript
复制
#!/usr/bin/env python3
"""合同关键信息抽取器:规则优先,结果落 CSV。仅依赖标准库。"""
import csv
import re
import sys
from pathlib import Path

# 字段名 -> (正则, 捕获组说明)。按合同常见写法设计,可按样本扩充。
RULES = {
    "party_a": r"甲\s*方[::]\s*([^\n,。;]+)",
    "party_b": r"乙\s*方[::]\s*([^\n,。;]+)",
    "amount": r"(?:合同)?(?:总)?金额[为::]*\s*(人民币)?\s*([\d,]+(?:\.\d+)?)\s*元",
    "term": r"(?:合同)?期限[为::]*\s*([^\n,。;]*?(?:年|月|日)[^\n,。;]*?)(?=[,。;\n])",
    "breach": r"违约责任[::]\s*([^\n。]*。)",
}


def extract_field(text: str, pattern: str) -> str:
    m = re.search(pattern, text)
    if not m:
        return ""
    groups = [g for g in m.groups() if g]
    return groups[-1].strip() if groups else m.group(0).strip()


def extract_file(path: Path) -> dict:
    text = path.read_text(encoding="utf-8")
    row = {"file": path.name}
    miss = []
    for field, pattern in RULES.items():
        value = extract_field(text, pattern)
        row[field] = value
        if not value:
            miss.append(field)
    row["miss"] = "|".join(miss)
    return row


def main(src_dir: str, out_csv: str):
    rows = [extract_file(p) for p in sorted(Path(src_dir).glob("*.txt"))]
    fields = ["file"] + list(RULES) + ["miss"]
    with open(out_csv, "w", encoding="utf-8-sig", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        writer.writerows(rows)
    hit = sum(1 for r in rows if not r["miss"])
    print(f"共处理 {len(rows)} 份,全字段命中 {hit} 份")


if __name__ == "__main__":
    main(sys.argv[1] if len(sys.argv) > 1 else "contracts",
         sys.argv[2] if len(sys.argv) > 2 else "result.csv")

三、验证:构造样例跑一遍

代码语言:javascript
复制
# make_sample.py:生成两份样例合同用于验证
from pathlib import Path

Path("contracts").mkdir(exist_ok=True)
Path("contracts/c1.txt").write_text(
    "甲方:云启科技有限公司\n乙方:某律师事务所\n"
    "合同总金额为人民币 1,200,000 元。\n"
    "合同期限为两年,自签署之日起算。\n"
    "违约责任:任何一方违约,应向对方支付合同总额 5% 的违约金。\n",
    encoding="utf-8")
Path("contracts/c2.txt").write_text(
    "甲方:恒通制造集团\n乙方:个人开发者\n"
    "合同期限为六个月。\n",
    encoding="utf-8")  # 故意缺金额与违约条款,验证 miss 列
print("样例已生成")
代码语言:javascript
复制
python3 make_sample.py && python3 extractor.py contracts result.csv

输出:

代码语言:javascript
复制
共处理 2 份,全字段命中 1 份

result.csv 中 c1 全部字段命中,c2 的 amount 和 breach 为空、miss 列标出缺失字段——这正是交付时要给客户演示的"系统知道自己的边界"。

四、从练手到作品的三步

第一步,接真实格式:PDF 用 pdfplumber 提取文本、docx 用 python-docx,抽取逻辑不用改,只是在 extract_file 前加一层格式转换。第二步,给规则兜底:对 miss 字段,把该字段上下文段落发给一个兼容 OpenAI 协议的模型服务(接口地址填 https://你的模型服务地址/v1/chat/completions),用提示词让它只回答字段值或"未提及",把结果与规则结果并列存入 CSV,人工抽查一致性。第三步,包装交付形态:加一个 30 行的 HTTP 上传页,客户拖文件进去、下载 CSV——能现场跑通的演示,比十页方案文档有说服力。

这个项目的价值不在代码量,而在它覆盖了 FDE 工作的完整链条:摸清需求边界、先跑通最小闭环、知道自己在哪里失效、留下扩展接口。把这个过程讲清楚,本身就是一次合格的现场演练。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、目标与边界
  • 二、完整代码 extractor.py
  • 三、验证:构造样例跑一遍
  • 四、从练手到作品的三步
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档