一、前期准备工作
1.1 软硬件环境配置
服务器最低配置:2核4G云服务器/本地服务器,操作系统使用CentOS7.9,镜像下载地址:https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/ ;客户端使用普通Win10及以上办公电脑即可,支持外接高速扫描仪。
1.2 必备工具安装
所有工具均为开源免费工具,可直接执行以下命令安装:
- 批量扫描工具:LiME v1.9.1,下载地址:https://github.com/504ensicsLabs/LiME/releases/tag/v1.9.1
- 数据库:MySQL8.0,CentOS环境执行安装命令:
yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm && yum install -y mysql-community-server && systemctl start mysqld && systemctl enable mysqld
- OCR识别工具:PaddleOCR开源版,Python3.7+环境执行安装命令:
pip install paddlepaddle==2.4.2 paddleocr==2.6.1.3 pandas pymysql
二、纸质档案数字化采集实操
2.1 纸质档案预处理
- 分类分拣:按接种人所属接种点、接种证编号排序,将破损、粘连、字迹模糊的档案单独分拣标注,优先处理完好档案
- 平整修复:拆除所有金属订书钉、回形针,褶皱页面用普通压书器压平30分钟以上,边缘破损页面用透明胶带在背面粘贴修复,避免遮挡文字
2.2 扫描参数配置
打开LiME扫描工具,按以下参数配置,配置完成后可保存为预设模板,后续批量扫描直接调用:
- 扫描分辨率:300DPI,低于该值会导致OCR识别准确率下降
- 色彩模式:24位真彩色,字迹偏淡的档案可适当调高对比度20%
- 存储格式:JPG,单文件大小控制在800KB-1M之间
- 自动命名规则:接种地区编码_接种人身份证号_扫描日期.jpg,例如:110101_110101199001011234_20240520.jpg
- 开启自动纠偏、自动去黑边、自动分页功能
2.3 结构化信息自动提取
将所有扫描好的JPG文件存入同一文件夹,新建Python文件extract.py,复制以下代码直接运行即可自动提取核心字段:
```python
from paddleocr import PaddleOCR
import os
import re
初始化OCR模型,仅识别中文、数字,关闭运行日志
ocr = PaddleOCR(use_angle_cls=True, lang='ch', show_log=False)
扫描件存放目录,可自行修改
SCAN_PATH = "./scan_files/"
提取结果输出目录
OUTPUT_PATH = "./extract_result/"
os.makedirs(OUTPUT_PATH, exist_ok=True)
身份证号正则校验规则
ID_CARD_PATTERN = re.compile(r'[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]')
for file_name in os.listdir(SCAN_PATH):
if not file_name.endswith(".jpg"):
continue
file_path = os.path.join(SCAN_PATH, file_name)
result = ocr.ocr(file_path, cls=True)
text_list = [line[1][0].strip() for line in result[0]]
extract_data = {
"area_code": file_name.split("_")[0],
"id_card": file_name.split("_")[1],
"name": "",
"vaccine_name": "",
"inoculate_date": "",
"unit": "",
"scan_file_url": file_path
}
for text in text_list:
if "姓名" in text:
extract_data["name"] = text.split("姓名")[-1].strip(":: ")
elif "疫苗名称" in text or "疫苗" in text:
extract_data["vaccine_name"] = text.split("疫苗")[-1].strip(":: 名称")
elif "接种日期" in text:
extract_data["inoculate_date"] = text.split("接种日期")[-1].strip(":: ").replace(".", "-")
elif "接种单位" in text:
extract_data["unit"] = text.split("接种单位")[-1].strip(":: ")
校验身份证号合法性,不合法则标记待人工复核
if not ID_CARD_PATTERN.match(extract_data["id_card"]):
extract_data["name"] = "待复核_" + extract_data["name"]
写入结果文件
with open(os.path.join(OUTPUT_PATH, file_name.replace(".jpg", ".txt")), "w", encoding="utf-8") as f:
for k, v in extract_data.items():
f.write(f"{k}:{v}\n")
```

运行完成后,所有提取结果会存入./extract_result/目录,平均识别准确率可达96%以上,仅需人工复核标记为“待复核”的文件即可,大幅降低人工录入成本。
三、档案数据库搭建与批量入库
3.1 数据库表结构创建
登录MySQL数据库,执行以下建表语句,可直接复制运行:
```sql
CREATE DATABASE IF NOT EXISTS inoculation_archive DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE inoculation_archive;
CREATE TABLE IF NOT EXISTS archive_info (
id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
area_code CHAR(6) NOT NULL COMMENT '接种地区编码',
id_card CHAR(18) NOT NULL COMMENT '接种人身份证号',
name VARCHAR(20) NOT NULL COMMENT '接种人姓名',
vaccine_name VARCHAR(50) NOT NULL COMMENT '疫苗名称',
inoculate_date DATE NOT NULL COMMENT '接种日期',
unit VARCHAR(100) NOT NULL COMMENT '接种单位',
scan_file_url VARCHAR(200) NOT NULL COMMENT '扫描件存储地址',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '入库时间',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uniq_idcard_vaccine (id_card, vaccine_name, inoculate_date) COMMENT '避免重复录入',
KEY idx_idcard (id_card) COMMENT '按身份证号查询加速',
KEY idx_inoculate_date (inoculate_date) COMMENT '按接种日期查询加速'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='预防接种档案主表';
```
3.2 批量入库操作
新建Python文件import_to_db.py,修改数据库连接信息后直接运行即可批量入库:
```python
import os
import pymysql
import pandas as pd
数据库连接信息,自行修改
DB_CONFIG = {
"host": "你的数据库IP",
"user": "root",
"password": "你的数据库密码",
"database": "inoculation_archive",
"charset": "utf8mb4"
}
EXTRACT_PATH = "./extract_result/"
conn = pymysql.connect(DB_CONFIG)
cursor = conn.cursor()
all_data = []
for file_name in os.listdir(EXTRACT_PATH):
if not file_name.endswith(".txt"):
continue
with open(os.path.join(EXTRACT_PATH, file_name), "r", encoding="utf-8") as f:
data = {}
for line in f.readlines():
k, v = line.strip().split(":", 1)
data[k] = v
all_data.append(data)
df = pd.DataFrame(all_data)
批量写入数据库
df.to_sql("archive_info", conn, if_exists="append", index=False)
conn.commit()
cursor.close()
conn.close()
print(f"成功入库{len(all_data)}条数据")
```
四、权限配置与校验验收
4.1 访问权限配置
执行以下SQL命令配置分级权限,避免数据被误改:
- 普通查询用户权限:
CREATE USER 'query_user'@'%' IDENTIFIED BY '自定义查询密码'; GRANT SELECT ON inoculation_archive. TO 'query_user'@'%'; FLUSH PRIVILEGES;
- 档案管理员权限:
CREATE USER 'admin_user'@'%' IDENTIFIED BY '自定义管理密码'; GRANT SELECT,INSERT,UPDATE ON inoculation_archive. TO 'admin_user'@'%'; FLUSH PRIVILEGES;
4.2 数据校验验收
按以下规则抽验数据,合格率达到99%以上即可上线使用:
- 随机抽取1%的入库数据,与原始纸质档案核对字段准确性
- 执行查询语句
SELECT FROM archive_info WHERE id_card = '测试身份证号',查询响应时间应低于100ms
- 检查重复数据:执行
SELECT id_card,vaccine_name,inoculate_date,COUNT() FROM archive_info GROUP BY id_card,vaccine_name,inoculate_date HAVING COUNT() >1;,返回结果应为空
五、常见问题排查
- OCR识别准确率低:检查扫描分辨率是否达到300DPI,页面是否有明显倾斜、污渍,重新扫描即可解决
- 入库失败:查看报错信息,90%以上为日期格式错误或重复数据,修改对应txt文件的字段内容后重新运行入库脚本即可
- 查询速度慢:确认已创建对应索引,单表100万级数据查询速度可稳定在100ms以内