本文目录导读:

针对脚本(通常指自动化脚本或程序代码)的合同文件分类归档,核心目标是自动化、结构化、可追溯,以下是一套基于脚本实现的分类归档方案,分为设计思路、具体实现步骤和示例代码三个部分。
核心设计思路
- 输入源:扫描指定文件夹(如“待归档合同”),或通过API接收文件。
- 信息提取:从PDF/Docx/图片合同中提取关键元数据(合同编号、甲方/乙方、签署日期、金额、合同类型)。
- 分类规则:基于提取的元数据(如甲方名称的首字母、合同类型、年份)自动生成文件夹层级。
- 归档执行:按规则移动或复制文件到新目录,并可能重命名。
- 日志与校验:记录每次操作,避免重复归档或错误处理。
详细实现步骤(以Python为例)
步骤1:环境准备
需要安装以下Python库:
os,shutil:文件操作pyPdf2/pdfplumber:读取PDF文本python-docx:读取Word文档pandas:处理分类规则表(如有)re:正则表达式提取数据
pip install pdfplumber python-docx pandas
步骤2:定义合同元数据结构
# 单个合同的信息字典
contract_info = {
"contract_id": "HT2023001",
"party_a": "某科技公司",
"party_b": "某服务商",
"sign_date": "2023-05-20",
"amount": 1000000.00,
"type": "技术服务合同", # 可来自文件名或内容关键词(如“采购”“租赁”“保密”)
"original_filename": "2023技术服务合同_某公司.pdf"
}
步骤3:信息提取函数(核心)
- PDF合同:用
pdfplumber逐页提取文本,然后用正则匹配“合同编号”“甲方”等。 - Word合同:用
python-docx读取段落或表格。 - 命名规范:若文件名已包含信息(如“HT2023-001-某公司-采购.pdf”),可优先解析文件名。
import re, pdfplumber
def extract_from_pdf(filepath):
text = ""
with pdfplumber.open(filepath) as pdf:
for page in pdf.pages:
text += page.extract_text()
# 示例正则:提取合同类型(假设文本包含“本合同为……合同”)
type_match = re.search(r'本合同为[\s]*([\u4e00-\u9fa5]+)[\s]*合同', text)
contract_type = type_match.group(1) if type_match else "其他"
# 类似提取其他字段...
return contract_type # 返回结构化字典
步骤4:分类规则引擎
def classify_rule(info):
"""
根据合同信息生成归档路径
示例规则:
/归档根目录/
{年度}/
{合同类型}/
{甲方首字母}/
{重命名后的文件}
"""
year = info['sign_date'][:4] if info['sign_date'] else "未知年份"
ctype = info['type'] if info['type'] else "其他"
# 甲方名称拼音首字母(可引入pypinyin库)
first_letter = get_first_letter(info['party_a'])
target_dir = os.path.join(ARCHIVE_ROOT, year, ctype, first_letter)
os.makedirs(target_dir, exist_ok=True)
return target_dir
步骤5:执行归档与日志
import shutil, datetime, csv
def archive_file(src_path, info):
target_dir = classify_rule(info)
# 重命名:合同编号_原始文件名(避免重名)
new_name = f"{info['contract_id']}_{info['original_filename']}"
target_path = os.path.join(target_dir, new_name)
shutil.move(src_path, target_path) # 或 copy2
# 写入日志.csv
with open('archive_log.csv', 'a', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow([datetime.now(), src_path, target_path, info['contract_id']])
步骤6:主流程循环扫描
import glob
ARCHIVE_ROOT = "D:/合同归档"
INPUT_FOLDER = "D:/待归档"
for filename in os.listdir(INPUT_FOLDER):
filepath = os.path.join(INPUT_FOLDER, filename)
if not os.path.isfile(filepath):
continue
# 跳过已归档标记(如文件名包含"_已归档")
if "_已归档" in filename:
continue
try:
info = extract_from_pdf(filepath) # 或 extract_from_docx
if info:
archive_file(filepath, info)
# 重命名原文件(可选)防止重复处理
os.rename(filepath, filepath.replace(".pdf", "_已归档.pdf"))
else:
# 无法提取则移到“未识别”文件夹
move_to_unknown(filepath)
except Exception as e:
log_error(filepath, str(e))
进阶优化建议
- 手写符号或样本的识别:如果合同中有手写的分类编号或签名,可结合OCR(如
pytesseract或百度API)进行识别。 - 重复归档检测:通过MD5哈希或合同编号,确保同一份合同不被重复归档。
- 性能提升:使用
multiprocessing或asyncio批量处理上百份文件。 - 用户交互:提供一个简单的GUI(如
tkinter)让用户手动确认提取的信息,避免误归。 - 分类规则动态化:将规则存储在JSON或Excel中,方便非技术人员修改(如增加“年份→客户→合同类型”的层级)。
示例流程示意图
[待归档文件夹]
├── 采购合同_华为_20231001.pdf
├── 技术服务合同_腾讯_2023.pdf
└── 租赁合同_利丰.docx
运行脚本后,自动生成:
[归档根目录]
├── 2023/
│ ├── 采购/
│ │ └── H/
│ │ └── HT2023-001_采购合同_华为_20231001.pdf
│ ├── 技术服务/
│ │ └── T/
│ │ └── HT2023-002_技术服务合同_腾讯_2023.pdf
│ └── 租赁/
│ └── L/
│ └── HT2023-003_租赁合同_利丰.docx
└── 未识别/
└── 模糊合同.png
常见问题处理
- 文件太模糊:设置置信度阈值,低于阈值时放入“待人工确认”文件夹。
- 合同类型识别不准:可采用关键词权重匹配(如“采购”出现5次以上才判为采购合同)。
- 存档路径冲突:生成唯一文件编号(如UUID),或判断目标目录是否已有同名文件并加后缀。
如果需要完整可运行的示例代码(包括PDF提取、Excel规则表、多线程扫描),我可以进一步提供。