事业单位档案数字化系统搭建实操全流程指南

一、技术栈选型与环境初始化

针对事业单位档案数字化项目,核心需求是高精度OCR识别、PDF/A长期保存格式支持以及符合DA/T 31标准的元数据管理。本指南采用Python作为核心开发语言,结合Tesseract OCR引擎和MySQL数据库,构建一套零成本、可私有化部署的数字化处理系统。

在Ubuntu 20.04 LTS服务器上执行以下命令进行基础环境依赖的安装。请确保系统已更新至最新内核版本以避免驱动兼容性问题。

1. 系统依赖安装

执行以下命令安装Python环境、图像处理库及OCR引擎:

```bash sudo apt update sudo apt install -y python3.8 python3-pip mysql-server mysql-client libmysqlclient-dev sudo apt install -y tesseract-ocr tesseract-ocr-chi-sim 安装Tesseract及中文语言包 sudo apt install -y ghostscript libimage-exiftool-perl 用于PDF/A转换和元数据提取 pip3 install pymysql pytesseract pdf2image pillow flask ```

2. 数据库初始化配置

登录MySQL并创建专用数据库。事业单位档案数据结构必须严格遵循档号、题名、责任者等核心字段。以下SQL脚本可直接复制执行:

```sql CREATE DATABASE archive_digital_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE archive_digital_dbi; CREATE TABLE archives ( id INT AUTO_INCREMENT PRIMARY KEY, archive_code VARCHAR(50) NOT NULL UNIQUE COMMENT '档号,唯一标识', title VARCHAR(255) NOT NULL COMMENT '题名', responsibility VARCHAR(100) COMMENT '责任者', date VARCHAR(20) COMMENT '日期', page_count INT DEFAULT 0 COMMENT '页数', ocr_text LONGTEXT COMMENT '全文识别结果', file_path VARCHAR(500) NOT NULL COMMENT '数字化文件存储路径', security_level TINYINT DEFAULT 1 COMMENT '保密等级:1-公开,2-内部,3-机密', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ```

二、核心OCR识别模块开发

OCR是档案数字化的核心。为了提高事业单位常见的红头文件、手写体识别率,我们需要对图像进行预处理(去噪、二值化)。创建名为ocr_engine.py的文件,并写入以下完整代码:

```python import pytesseract from PIL import Image, ImageEnhance, ImageFilter import os class ArchiveOCR: def __init__(self, lang='chi_sim'): self.lang = lang 验证Tesseract是否安装 if not os.system('which tesseract > /dev/null 2>&1'): pass else: raise EnvironmentError("Tesseract未安装,请执行 apt install tesseract-ocr") def preprocess_image(self, image_path): """ 图像预处理:转灰度、增强对比度、去噪 """ img = Image.open(image_path) 转换为灰度图 img = img.convert('L') 增强对比度 enhancer = ImageEnhance.Contrast(img) img = enhancer.enhance(2.0) 二值化处理 img = img.point(lambda x: 0 if x < 140 else 255, '1') return img def recognize(self, image_path): """ 执行OCR识别 """ try: processed_img = self.preprocess_image(image_path) 配置识别参数:psm 6假设为单行文本块,但档案通常是混合文本,使用默认或psm 3 custom_config = r'--oem 3 --psm 3' text = pytesseract.image_to_string(processed_img, lang=self.lang, config=custom_config) return text.strip() except Exception as e: print(f"识别失败 {image_path}: {str(e)}") return "" 测试代码 if __name__ == "__main__": ocr = ArchiveOCR() 请确保当前目录下有test.jpg,否则会报错 print(ocr.recognize("test.jpg")) ```

三、PDF/A格式转换与封装

事业单位档案长期保存必须符合ISO 19005标准(PDF/A)。普通的PDF无法保证长期可读性。我们使用Ghostscript进行转换。创建pdf_converter.py

```python import subprocess import os def convert_to_pdfa(input_pdf, output_pdf): """ 使用Ghostscript将普通PDF转换为PDF/A-1b标准 """ 检查输入文件是否存在 if not os.path.exists(input_pdf): raise FileNotFoundError(f"源文件 {input_pdf} 不存在") Ghostscript转换命令 -dPDFA: 开启PDF/A模式 -dPDFACompatibilityPolicy=1: 遇到不兼容时报错 cmd = [ "gs", "-dPDFA", "-dBATCH", "-dNOPAUSE", "-dQUIET", "-sDEVICE=pdfwrite", "-dPDFACompatibilityPolicy=1", "-dColorConversionStrategy=/UseDeviceIndependentColor", "-dProcessColorModel=/DeviceRGB", "-sOutputFile=" + output_pdf, input_pdf ] try: result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if result.returncode == 0: return True else: print(f"转换错误: {result.stderr.decode('utf-8')}") return False except subprocess.CalledProcessError as e: print(f"Ghostscript执行失败: {e.stderr.decode('utf-8')}") return False ```

四、业务逻辑集成与API接口

将OCR、转换和数据库操作封装为Web API。创建app.py,这是整个系统的入口,实现了文件上传、自动识别、归档入库的全流程。

```python from flask import Flask, request, jsonify import pymysql import os import uuid from datetime import datetime from ocr_engine import ArchiveOCR from pdf_converter import convert_to_pdfa app = Flask(__name__) 配置项 UPLOAD_FOLDER = '/data/archive_uploads' STORAGE_FOLDER = '/data/archive_storage' os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(STORAGE_FOLDER, exist_ok=True) 数据库连接配置 DB_CONFIG = { 'host': 'localhost', 'user': 'root', 'password': 'your_password', 请修改为实际MySQL密码 'database': 'archive_digital_db', 'charset': 'utf8mb4' } def get_db_connection(): return pymysql.connect(DB_CONFIG) @app.route('/api/upload', methods=['POST']) def upload_archive(): """ 档案上传接口 参数:file(文件), title(题名), code(档号), responsibility(责任者) """ if 'file' not in request.files: return jsonify({"error": "无文件上传"}), 400 file = request.files['file'] title = request.form.get('title') code = request.form.get('code') resp = request.form.get('responsibility') if not code or not title: return jsonify({"error": "档号和题名为必填项"}), 400 1. 保存临时文件 temp_filename = f"{uuid.uuid4().hex}_{file.filename}" temp_path = os.path.join(UPLOAD_FOLDER, temp_filename) file.save(temp_path) 2. 判断文件类型并处理 ocr_text = "" final_pdf_path = "" try: if file.filename.lower().endswith('.pdf'): 如果是PDF,先转PDF/A final_pdf_name = f"{code}.pdf" final_pdf_path = os.path.join(STORAGE_FOLDER, final_pdf_name) if not convert_to_pdfa(temp_path, final_pdf_path): return jsonify({"error": "PDF/A转换失败"}), 500 简单的PDF转图片OCR逻辑(需安装pdf2image,此处仅演示第一页) 实际生产环境需遍历所有页面 from pdf2image import convert_from_path images = convert_from_path(final_pdf_path, first_page=True) if images: ocr_engine = ArchiveOCR() 保存第一页为临时jpg供OCR使用 temp_img = os.path.join(UPLOAD_FOLDER, "temp_ocr.jpg") images[0].save(temp_img, 'JPEG') ocr_text = ocr_engine.recognize(temp_img) os.remove(temp_img) elif file.filename.lower().endswith(('.jpg', '.jpeg', '.png')): 如果是图片,先OCR,再封装为PDF/A ocr_engine = ArchiveOCR() ocr_text = ocr_engine.recognize(temp_path) 图片转PDF (使用ImageMagick或PIL,这里简化处理,假设后续手动打包或使用img2pdf) 为简化代码,此处仅记录图片路径,实际需转PDF final_pdf_path = temp_path else: return jsonify({"error": "不支持的文件格式"}), 400 3. 写入数据库 conn = get_db_connection() try: with conn.cursor() as cursor: sql = "INSERT INTO archives (archive_code, title, responsibility, ocr_text, file_path) VALUES (%s, %s, %s, %s, %s)" cursor.execute(sql, (code, title, resp, ocr_text, final_pdf_path)) conn.commit() finally: conn.close() return jsonify({"message": "归档成功", "archive_code": code, "ocr_preview": ocr_text[:100]}) except Exception as e: return jsonify({"error": str(e)}), 500 finally: 清理临时文件 if os.path.exists(temp_path) and temp_path != final_pdf_path: os.remove(temp_path) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ```

五、系统部署与验证

代码编写完成后,需进行服务化部署。使用systemd管理Flask进程,确保开机自启。

1. 修改数据库密码

打开app.py,将your_password替换为MySQL的实际root密码或专用账号密码。

事业单位档案数字化系统搭建实操全流程指南

2. 启动服务

为了方便测试,先直接运行:

```bash python3 app.py ```

服务将在5000端口启动。

3. 功能验证

使用curl命令模拟文件上传,验证OCR和入库流程:

```bash 准备一张测试图片 test.jpg 和 测试PDF test.pdf curl -X POST -F "file=@test.jpg" -F "title=2023年度工作总结" -F "code=2023-ZONGJIE-001" -F "responsibility=办公室" http://localhost:5000/api/upload ```

预期返回JSON结果包含"归档成功"及OCR识别出的前100个文字预览。此时登录MySQL数据库,执行SELECT FROM archives;即可看到入库的记录。

六、常见问题排查

1. Tesseract识别乱码

请确保已安装tesseract-ocr-chi-sim包。如果识别率低,需在ocr_engine.py中调整二值化阈值(当前为140),或者下载更精确的训练字库替换系统默认字库。

2. PDF转换失败

Ghostscript对某些特殊字体支持不佳。如果报错,尝试在转换命令中添加-dSubsetFonts=true参数,或者检查源PDF是否加密。

3. 权限错误

确保/data/archive_uploads/data/archive_storage目录对运行Python脚本的用户具有读写权限。通常执行chmod 777 /data/archive_可快速解决测试环境权限问题。

AI咨询
热线电话

028-85154420

15388110056

全国售前咨询电话

扫码咨询
安答联动微信公众号二维码

微信扫码关注安答联动

申请试用
热线电话
申请试用

安答联动档案管理系统