一、环境准备与依赖安装
在进行文书档案移交前,必须确保操作环境具备处理元数据XML生成、文件重命名及打包压缩的能力。本方案采用Python作为核心脚本语言,因其具备强大的文件处理能力和丰富的第三方库支持。请确保你的操作系统已安装Python 3.8或更高版本。
打开终端或命令提示符,执行以下命令安装必要的依赖库。这里我们使用pandas处理Excel元数据,lxml生成符合标准的XML文件,openpyxl用于读写xlsx文件:
```bash
pip install pandas lxml openpyxl
```
安装完成后,建议在项目根目录下创建以下文件夹结构,以便规范操作:
- source_files/:存放待移交的原文电子文件(如PDF、OFD)。
- metadata/:存放整理好的元数据Excel文件。
- output/:存放最终生成的移交包。
二、元数据规范与模板配置
档案移交的核心难点在于元数据的标准化。大多数接收方(如档案馆)要求提供符合DA/T标准或特定业务规范的XML文件。我们需要先定义一个清晰的元数据映射关系。
假设你的元数据存储在metadata/archives.xlsx中,Excel表头必须包含以下关键字段(可根据实际需求增减,但以下字段为通用核心字段):
- 档号:全宗号-目录号-案卷号-件号。
- 题名:文件标题。
- 责任者:发文单位或个人。
- 日期:文件形成日期,格式为YYYYMMDD。
- 页数:文件总页数。
- 文件名:对应
source_files中的原始文件名。
- 密级:公开/内部/机密等。
三、核心脚本编写:XML生成与文件挂接
创建一个名为transfer_system.py的文件。我们将分步实现读取Excel、构建XML树、重命名文件并打包的逻辑。以下是完整的、可直接运行的代码:
```python
import os
import shutil
import pandas as pd
from lxml import etree
from datetime import datetime
import zipfile
配置路径
SOURCE_DIR = 'source_files'
METADATA_FILE = 'metadata/archives.xlsx'
OUTPUT_DIR = 'output'
TEMP_DIR = 'output/temp_package'
def ensure_dir(directory):
if not os.path.exists(directory):
os.makedirs(directory)
def generate_xml(row_data):
"""
根据Excel行数据生成标准的档案XML元数据
"""
root = etree.Element("档案著录")
基础字段映射
fields = [
("档号", "档号"),
("题名", "题名"),
("责任者", "责任者"),
("日期", "日期"),
("页数", "页数"),
("密级", "密级"),
("载体类型", "纸质"), 默认值
("电子文件名", row_data['档号'] + ".pdf") 统一重命名规则
]
for cn_name, value in fields:
elem = etree.SubElement(root, cn_name)
elem.text = str(value)
生成XML字符串,声明为UTF-8编码
xml_str = etree.tostring(root, encoding='utf-8', pretty_print=True, xml_declaration=True)
return xml_str.decode('utf-8')
def process_transfer():
print(f"开始处理移交任务,时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
1. 读取元数据
if not os.path.exists(METADATA_FILE):
print(f"错误:找不到元数据文件 {METADATA_FILE}")
return
df = pd.read_excel(METADATA_FILE)
print(f"读取到 {len(df)} 条元数据记录。")
清理并创建临时目录
if os.path.exists(TEMP_DIR):
shutil.rmtree(TEMP_DIR)
ensure_dir(TEMP_DIR)
ensure_dir(os.path.join(TEMP_DIR, "原文"))
ensure_dir(os.path.join(TEMP_DIR, "元数据"))
success_count = 0
error_log = []
2. 遍历处理每一条记录
for index, row in df.iterrows():
try:
archival_code = str(row['档号']).strip()
original_filename = str(row['文件名']).strip()
source_file_path = os.path.join(SOURCE_DIR, original_filename)
确定新的文件名(通常使用档号作为文件名,扩展名保持不变)
ext = os.path.splitext(original_filename)[1]
new_filename = f"{archival_code}{ext}"
步骤A: 复制并重命名原文
if os.path.exists(source_file_path):
dest_file_path = os.path.join(TEMP_DIR, "原文", new_filename)
shutil.copy2(source_file_path, dest_file_path)
else:
error_log.append(f"原文缺失: {original_filename} (档号: {archival_code})")
即使原文缺失,也继续生成XML,或者根据需求跳过
continue
步骤B: 生成XML元数据文件
xml_content = generate_xml(row)
xml_filename = f"{archival_code}.xml"
xml_path = os.path.join(TEMP_DIR, "元数据", xml_filename)
with open(xml_path, 'w', encoding='utf-8') as f:
f.write(xml_content)
success_count += 1
except Exception as e:
error_log.append(f"处理档号 {row.get('档号', '未知')} 时出错: {str(e)}")
3. 打包压缩
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
zip_name = f"档案移交包_{timestamp}.zip"
zip_path = os.path.join(OUTPUT_DIR, zip_name)
print(f"正在打包压缩...")
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(TEMP_DIR):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, TEMP_DIR)
zipf.write(file_path, arcname)
4. 输出报告
print("-" 30)
print(f"处理完成!")
print(f"成功移交: {success_count} 件")
print(f"失败/跳过: {len(error_log)} 件")
print(f"移交包路径: {os.path.abspath(zip_path)}")
if error_log:
print("\n错误详情:")
for err in error_log:
print(err)
if __name__ == "__main__":
process_transfer()
```
四、操作步骤详解
上述代码实现了从Excel读取元数据、匹配原文文件、生成标准化XML并最终打包压缩的全流程。以下是执行该脚本的详细步骤及注意事项:
1. 数据校验
在运行脚本前,请务必检查source_files文件夹中的文件名是否与Excel中的“文件名”列完全一致(包括扩展名的大小写)。如果系统是Linux环境,文件名大小写敏感;如果是Windows,则不敏感,但建议保持一致以养成良好习惯。
2. 执行脚本
在终端中运行以下命令启动移交程序:
```bash
python transfer_system.py
```

脚本运行时,会实时在控制台输出进度。如果遇到“原文缺失”的错误,请检查源文件夹路径是否正确,或者Excel中的文件名是否存在空格等不可见字符。
3. 结果验证
脚本执行完毕后,进入output目录,你会看到一个以时间戳命名的ZIP文件。解压该文件,你应该能看到标准的移交结构:
- 元数据/:里面存放着与档号同名的XML文件,每条记录一个。
- 原文/:里面存放着已经按照档号重命名后的电子文件。
随机抽取一个XML文件,用文本编辑器打开,检查内容是否包含乱码(应确保为UTF-8编码),并核对字段是否与Excel一致。
五、进阶优化:电子文件计算校验码
为了保证移交数据的完整性,接收方往往要求提供电子文件的校验码(如MD5或SHA-256)。我们需要对上述脚本进行微调,在生成XML时加入校验码字段。
引入Python标准库hashlib。在process_transfer函数的循环中,复制文件后立即计算其哈希值:
```python
import hashlib
def calculate_file_hash(file_path, algorithm='md5'):
hash_func = hashlib.new(algorithm)
with open(file_path, 'rb') as f:
while chunk := f.read(8192):
hash_func.update(chunk)
return hash_func.hexdigest()
在 process_transfer 循环中,shutil.copy2 之后添加:
file_hash = calculate_file_hash(dest_file_path, 'sha256')
row['电子文件校验码'] = file_hash 将校验码动态加入row字典,供XML生成使用
```
接着,修改generate_xml函数中的fields列表,增加校验码字段的映射:
```python
在 fields 列表中添加
fields = [
... 其他字段 ...
("电子文件校验码", "电子文件校验码"),
("校验算法", "SHA256")
]
```
这样生成的XML文件中就会包含每份电子文件的唯一数字指纹,极大地提升了移交包的可信度,防止数据在传输过程中被篡改或损坏。
六、常见报错处理方案
在实际操作中,可能会遇到以下典型问题,请参考对应的解决方案:
- 报错:ModuleNotFoundError: No module named 'openpyxl'
原因:未正确安装依赖库。
解决:重新执行pip install pandas openpyxl lxml。
- 报错:FileNotFoundError: [Errno 2] No such file or directory: 'metadata/archives.xlsx'
原因:脚本找不到Excel文件,通常是工作目录(Working Directory)不对。
解决:确保在终端中cd到了脚本所在的目录再运行python命令。
- XML文件打开乱码
原因:系统默认编码可能不是UTF-8,或者编辑器打开方式错误。
解决:代码中已强制指定UTF-8写入,请使用VS Code或Notepad++等支持UTF-8的编辑器打开,确保无BOM头。
- 打包后文件体积过大
原因:原文中包含大量高分辨率图片或未压缩的PDF。
解决:在shutil.copy2之前增加一步图片压缩逻辑,或者移交前手动对原文进行瘦身处理。
通过以上步骤,你已完成了一套标准化的文书档案系统移交流程。该方案剥离了对昂贵商业软件的依赖,完全基于开源技术栈,实现了从数据整理到最终交付的自动化闭环,能够直接应用于绝大多数企事业单位的档案数字化移交项目。