背景
之前帮家人买过几次彩票,验奖时发现体验挺麻烦的:要么去投注站扫描,要么手动一个个核对号码。作为程序员当然想到能不能写个工具解决,于是就有了这个小程序项目。
技术选型上选择了微信小程序 + 腾讯云开发(CloudBase),主要是看中了云开发的 Serverless 架构,省去了运维的麻烦,可以专注在业务逻辑上。
核心技术实现
1. OCR 识别 + LLM 解析的组合方案
最开始的想法是直接用 OCR 识别彩票上的号码,但实际遇到了几个问题:
- 彩票样式五花八门,双色球、大乐透、福彩 3D 等格式都不一样光学识别出文字后,还要定位哪些是投注号码、哪些是期号、站点编号等号码排列有时是横向有时是纵向,传统规则解析很难覆盖所有情况
后来采用了 OCR + LLM 结构化提取 的方案:
// 1. 先用腾讯云 OCR 识别文字const ocrResult = await customOCRService.detectFromDataURL(imageData);// 2. 将 OCR 结果交给智谱 AI 的 LLM 进行结构化解析const lotteryInfo = await parseLotteryByZhipuLLM(ocrResult.ocr_result);// 3. 获取开奖数据进行比对const issue = await getIssue(app, lotteryType, lotteryInfo.issue);const calcRes = await calculateWinning(lotteryInfo, issue);LLM 的好处是可以理解上下文,自动识别出"这是双色球"、"这些是红球号码"、"这是蓝球",准确率比纯规则匹配高很多。
2. 云托管 + 数据模型设计
后端采用云托管(Cloud Run)部署 Express 服务,配合 CloudBase SDK 操作数据库:
// 使用数据模型而不是直接操作 databaseconst models = cloudBaseClient.getModels();await models.tickets.create({ data: { lottery_type, issue, numbers, status: isOpened ? 'winning' : 'undrawn', _openid: openId // 安全隔离,每个用户只能查看自己的数据 }});这样做的好处:
- 数据模型层面自动处理权限隔离(通过
_openid)统一的数据访问接口,避免到处写 collection().where()更容易做单元测试和代码复用3. 订阅通知的实现
未开奖的彩票可以订阅开奖通知,技术上用的是微信小程序订阅消息能力:
// 前端申请订阅权限wx.requestSubscribeMessage({ tmplIds: ['xxx'], success: (res) => { // 调用后端接口记录订阅 callCloudApi('/api/message/subscribe', { ticketId, issue }) }})// 后端定时任务检查开奖// 当检测到新期开奖时,批量推送消息给订阅用户一些坑和优化
1. 图片压缩问题
最初直接上传原图,有些用户拍照动辄 5-8MB,上传慢还占存储。后来加了前端压缩,限制宽度 1200px,质量 0.8,效果不错。
2. OCR 成本控制
腾讯云 OCR 按次计费,为了省钱做了些优化:
- 前端裁剪功能,让用户只上传彩票部分缓存识别结果,避免重复识别同一张图
功能亮点
- 拍照即验奖: 拍照上传,2-3 秒出结果,自动计算奖金订阅开奖通知: 未开奖彩票可订阅,开奖后自动推送验奖结果票夹管理: 自动保存验奖历史,支持按状态筛选(中奖/未中奖/未开奖)适配多玩法: 目前支持双色球、大乐透、福彩 3D 等主流玩法
技术栈总结
- 前端: 微信小程序原生框架后端: Express + CloudBase Node SDK数据库: 云开发 NoSQL 数据库AI 能力: 腾讯云 OCR + 智谱 AI GLM-4存储: 云开发对象存储
一些思考
这个项目让我对 OCR + LLM 结合 有了新的认识。传统做法是 OCR 识别后用正则或规则提取信息,但面对非标准化的场景(比如各种彩票样式),维护成本很高。引入 LLM 做结构化提取后,准确率和鲁棒性都提升了不少,而且几乎不需要针对新样式单独写规则。
另外云开发这种 Serverless 模式确实适合个人开发者,不用操心服务器、域名备案、数据库运维这些琐事,专注写业务逻辑就行。
小程序搜索"彩运多"可以体验,欢迎交流技术实现细节。
项目还在持续优化中,后续计划:
- 支持刮刮乐彩票拍照验奖 提升视觉解析速度 增加中奖统计分析功能
