基于GLM-OCR的数据库课程设计:票据信息自动化录入系统

发布时间:2026/7/12 18:22:21

基于GLM-OCR的数据库课程设计:票据信息自动化录入系统 基于GLM-OCR的数据库课程设计票据信息自动化录入系统每次做课程设计是不是都觉得有点枯燥要么是纯理论的增删改查要么是做个简单的管理系统感觉和现在流行的技术有点脱节。我最近带着学生做了一个挺有意思的项目把AI里的OCR技术和传统的数据库课程设计结合了起来。简单说就是做一个能自动“看懂”发票、报销单这些票据然后把里面的关键信息比如金额、日期自动存到数据库里的系统。听起来是不是比单纯做个学生信息管理系统要酷一点这个项目特别适合计算机专业的同学或者刚入门想找个实战项目的开发者。它把几个关键技能点都串起来了AI模型调用、数据清洗、数据库设计还有前后端交互。做完之后你不仅能掌握数据库的核心操作还能亲身体验AI是怎么给传统的数据处理流程“提效”的。下面我就把这个项目的完整思路和关键实现步骤分享给你。1. 项目核心思路当数据库遇上AI我们先来聊聊为什么要做这个。你想啊以前公司财务处理票据要么手动敲键盘录入Excel要么用扫描仪加软件步骤繁琐还容易出错。我们这个系统的目标就是让这个过程自动化。核心流程其实就三步拍个照或上传图片用户把发票、车票拍下来传到系统里。让AI“看懂”图片系统调用GLM-OCR模型识别图片上的文字特别是我们关心的金额、日期、发票号码这些。把结果存起来系统把识别出来的结构化数据整理干净后自动存入MySQL数据库的对应表格里。这样一来一个原本需要人工核对、手动录入的活儿就变成了秒级完成的自动化操作。对于课程设计来说这个项目既有明确的业务场景票据管理又涵盖了从AI接口调用到数据落地的完整技术链内容足够丰富也很有实用价值。2. 系统设计与技术选型在动手写代码之前我们得先把系统的架子搭好知道每个部分用什么技术来实现。2.1 系统架构概览整个系统可以分成四个主要部分像一条流水线前端界面用户上传票据图片、查看识别结果和管理数据的窗口。为了快速原型开发我们可以用Vue.js或React这些前端框架搭配Element Plus或Ant Design这样的UI组件库能省下很多设计样式的时间。后端服务负责处理业务逻辑的“大脑”。它接收前端传来的图片去调用OCR服务处理返回的数据最后和数据库打交道。Python的Flask或FastAPI框架非常轻量灵活适合这种项目。OCR识别引擎这就是项目的“AI眼睛”。我们选择GLM-OCR因为它对中文场景的印刷体、手写体识别效果比较好而且通常有提供方便的API接口供我们调用。数据库存储所有结构化数据的大本营。MySQL是经典选择稳定、易学和课程设计主题完美契合。它们之间的关系很简单前端请求后端后端调用OCROCR返回文字后端处理文字并存入数据库最后把结果返回给前端展示。2.2 数据库表设计数据库设计是课程设计的核心。我们至少需要两张表票据原始记录表 (bill_raw)存放最原始的信息。字段名类型说明idINT (主键)自增的唯一IDimage_pathVARCHAR(255)上传的票据图片存储路径upload_timeDATETIME上传时间ocr_raw_textTEXTOCR识别出来的全部原始文本可能杂乱票据结构化信息表 (bill_structured)存放清洗后我们真正关心的关键信息。字段名类型说明idINT (主键)自增的唯一IDbill_idINT (外键)关联bill_raw.idbill_numberVARCHAR(50)发票号码bill_dateDATE开票日期total_amountDECIMAL(10,2)总金额含税tax_amountDECIMAL(10,2)税额payerVARCHAR(100)付款方payeeVARCHAR(100)收款方categoryVARCHAR(50)票据类别如餐饮、交通extraction_statusTINYINT信息提取状态0:失败, 1:成功, 2:需人工复核这样设计的好处是把原始数据和加工后的数据分开如果后续识别算法升级我们可以重新处理原始文本而不用动已结构化的数据。3. 关键实现步骤详解架子搭好了我们来一步步实现核心功能。这里我会用 Python Flask 作为后端示例。3.1 第一步搭建基础后端与OCR调用首先确保你的环境安装了必要的包flask,requests,pymysql。# app.py from flask import Flask, request, jsonify import requests import json import re from datetime import datetime app Flask(__name__) # 假设GLM-OCR的API端点实际使用时替换为真实URL和密钥 GLM_OCR_API_URL https://api.example.com/glm-ocr/v1/recognize API_KEY your_api_key_here def call_glm_ocr(image_path): 调用GLM-OCR API识别图片文字 headers {Authorization: fBearer {API_KEY}} files {image: open(image_path, rb)} try: response requests.post(GLM_OCR_API_URL, headersheaders, filesfiles) response.raise_for_status() # 检查请求是否成功 result response.json() # 假设API返回格式为 {text: 识别出的全部文字, blocks: [...]} return result.get(text, ) except requests.exceptions.RequestException as e: print(fOCR API调用失败: {e}) return None finally: files[image].close() app.route(/api/upload, methods[POST]) def upload_and_ocr(): 处理图片上传并调用OCR if file not in request.files: return jsonify({error: 没有文件上传}), 400 file request.files[file] if file.filename : return jsonify({error: 未选择文件}), 400 # 保存上传的图片实际项目应考虑更安全的存储和文件名生成 save_path f./uploads/{datetime.now().strftime(%Y%m%d_%H%M%S)}_{file.filename} file.save(save_path) # 调用OCR raw_text call_glm_ocr(save_path) if raw_text is None: return jsonify({error: OCR识别服务暂不可用}), 500 # 这里可以先返回原始文本前端预览后续再触发信息提取 return jsonify({ message: 上传成功, image_path: save_path, raw_text: raw_text }), 200 if __name__ __main__: app.run(debugTrue)这段代码建立了最基础的后端服务。有一个/api/upload接口接收图片保存到本地然后调用GLM-OCR的API你需要替换成真实的地址和密钥最后把识别出的原始文本返回。3.2 第二步从杂乱文本中提取关键信息OCR识别出来的文字通常是一大段夹杂着无关信息。我们需要写一个“信息提取器”把金额、日期等“挖”出来。这里用正则表达式做简单演示实际项目中可以考虑用更高级的自然语言处理技术。# info_extractor.py import re from dateutil import parser def extract_bill_info(raw_text): 从OCR原始文本中提取结构化信息。 这是一个基础示例实际规则需要根据大量票据样本调整。 info { bill_number: None, bill_date: None, total_amount: None, tax_amount: None, payer: None, payee: None, category: None } # 1. 提取金额寻找“金额”、“合计”、“小写”等关键词后的数字 # 匹配如“123.45”、“123.45元”、“1,234.56”等格式 amount_patterns [ r(?:金额|合计|小写|总价)[:]?\s*[¥]?\s*([0-9,](?:\.[0-9]{2})?), r[¥]\s*([0-9,](?:\.[0-9]{2})?) ] for pattern in amount_patterns: matches re.findall(pattern, raw_text) if matches: # 取最后一个匹配到的金额常为总金额 amount_str matches[-1].replace(,, ) try: info[total_amount] float(amount_str) except ValueError: pass break # 2. 提取日期寻找“日期”、“时间”、“开票日期”等关键词 date_patterns [ r(?:日期|时间|开票日期)[:]?\s*(\d{4}[-/年]\d{1,2}[-/月]\d{1,2}日?), r(\d{4}[-/年]\d{1,2}[-/月]\d{1,2}日?) ] for pattern in date_patterns: match re.search(pattern, raw_text) if match: date_str match.group(1) try: # 尝试解析多种格式的日期 parsed_date parser.parse(date_str, fuzzyTrue) info[bill_date] parsed_date.strftime(%Y-%m-%d) except (ValueError, OverflowError): pass break # 3. 提取发票号码通常由数字和字母组成可能包含“No.”、“编号”等前缀 invoice_pattern r(?:发票号码|号码|No\.|编号)[:]?\s*([A-Z0-9-]) match re.search(invoice_pattern, raw_text, re.IGNORECASE) if match: info[bill_number] match.group(1).strip() # 4. 简单分类根据关键词判断票据类别 categories { 餐饮: [餐费, 饭店, 餐厅, 食品], 交通: [车票, 出租车, 汽油, 通行费], 办公: 办公用品|文具|打印, 住宿: 酒店|住宿|旅馆 } for category, keywords in categories.items(): if isinstance(keywords, list): if any(keyword in raw_text for keyword in keywords): info[category] category break elif re.search(keywords, raw_text): info[category] category break return info这个提取器虽然简单但已经能处理很多常见票据了。你可以把它集成到Flask的后端接口里在OCR识别后立即调用或者单独提供一个接口让前端触发提取。3.3 第三步连接数据库并存储结果信息提取出来后就该存入MySQL了。我们需要建立数据库连接并完成插入操作。# db_utils.py import pymysql from config import DB_CONFIG # 从配置文件读取数据库连接信息 def get_db_connection(): 获取数据库连接 return pymysql.connect( hostDB_CONFIG[host], userDB_CONFIG[user], passwordDB_CONFIG[password], databaseDB_CONFIG[database], charsetutf8mb4 ) def save_bill_record(image_path, raw_text, structured_info): 将票据记录存入数据库。 返回插入的结构化信息ID。 conn get_db_connection() cursor conn.cursor() try: # 1. 插入原始记录 sql_raw INSERT INTO bill_raw (image_path, upload_time, ocr_raw_text) VALUES (%s, NOW(), %s) cursor.execute(sql_raw, (image_path, raw_text)) raw_id cursor.lastrowid # 2. 插入结构化信息 sql_structured INSERT INTO bill_structured (bill_id, bill_number, bill_date, total_amount, tax_amount, payer, payee, category, extraction_status) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) # 判断提取是否成功这里简单认为提取到金额或日期就算成功 status 1 if (structured_info.get(total_amount) or structured_info.get(bill_date)) else 2 cursor.execute(sql_structured, ( raw_id, structured_info.get(bill_number), structured_info.get(bill_date), structured_info.get(total_amount), structured_info.get(tax_amount), structured_info.get(payer), structured_info.get(payee), structured_info.get(category), status )) conn.commit() return cursor.lastrowid except Exception as e: conn.rollback() print(f数据库操作失败: {e}) return None finally: cursor.close() conn.close()然后在你的Flask上传接口中在提取信息后调用这个保存函数整个从上传到存储的闭环就完成了。3.4 第四步前端界面与用户交互前端主要负责两件事上传图片和展示结果。这里给一个非常简化的Vue组件示例展示核心逻辑。!-- BillUpload.vue -- template div h3上传票据图片/h3 input typefile changehandleFileUpload acceptimage/* / button clickuploadFile :disabled!file开始识别/button div v-ifuploading正在上传并识别.../div div v-ifresult h4识别结果/h4 pstrong原始文本/strongbr{{ result.raw_text }}/p div v-ifresult.extracted_info h5提取的关键信息/h5 ul li发票号码{{ result.extracted_info.bill_number || 未识别 }}/li li日期{{ result.extracted_info.bill_date || 未识别 }}/li li总金额{{ result.extracted_info.total_amount || 未识别 }}/li li类别{{ result.extracted_info.category || 未识别 }}/li /ul p状态{{ result.status 1 ? 自动提取成功 : 建议人工复核 }}/p /div /div /div /template script import axios from axios; export default { data() { return { file: null, uploading: false, result: null }; }, methods: { handleFileUpload(event) { this.file event.target.files[0]; }, async uploadFile() { if (!this.file) return; const formData new FormData(); formData.append(file, this.file); this.uploading true; this.result null; try { // 调用后端上传接口 const uploadResp await axios.post(/api/upload, formData); // 调用后端信息提取接口假设为 /api/extract const extractResp await axios.post(/api/extract, { image_path: uploadResp.data.image_path, raw_text: uploadResp.data.raw_text }); this.result extractResp.data; // 包含提取信息和状态 } catch (error) { console.error(处理失败:, error); alert(处理失败请重试。); } finally { this.uploading false; } } } }; /script这个前端页面让用户可以选择图片文件点击上传后会先后调用后端的两个接口上传OCR和提取信息最后把识别出的原始文本和提取出的关键信息清晰地展示出来。4. 项目扩展与优化建议一个基本的系统做完后你可以考虑加入更多功能让它更像一个“产品”这也是课程设计拿高分的关键。批量处理修改前端和后端支持一次上传多张图片后端用队列比如Celery异步处理避免界面卡死。人工复核界面对于提取状态为“需人工复核”的记录做一个专门的界面展示原始图片、OCR文本和一个表单让用户可以方便地修正错误信息并确认入库。数据查询与统计做一个数据看板可以按时间、类别、金额范围查询票据并生成简单的统计图表如月度开销趋势、类别占比这里就能充分练习SQL的复杂查询和聚合操作。提升识别准确率现在的信息提取器基于规则比较脆弱。你可以尝试收集更多票据样本优化正则表达式。使用基于机器学习的方法如训练一个简单的命名实体识别NER模型来定位关键字段。如果GLM-OCR支持研究其返回的文本块位置信息利用版面分析来更准确地定位“金额”、“日期”等标签旁边的文字。5. 总结把这个项目做下来你会发现它完全覆盖了数据库课程设计的要求从概念模型、逻辑模型到物理模型的设计与实现完成了增删改查所有操作并可能涉及事务、连接查询等高级特性。更重要的是它为你打开了一扇窗让你亲手实践了如何将一项前沿的AI能力OCR与传统的信息管理系统相结合解决一个真实的痛点。过程中最花时间的可能不是写SQL或者API而是调整那个信息提取的规则让它能适应五花八门的票据格式。但这正是工程实践有趣的地方——没有标准答案需要你不断观察、测试和迭代。建议你在实现基本功能后多找几张真实的发票图片试试看看哪里会出错然后想办法改进它。这个过程积累的经验远比单纯抄一个管理系统代码要宝贵得多。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关新闻