公司动态

Cursor 赋能 RPA 机器人开发:大模型接口调用 + OCR 非结构化数据完整源码实战

📅 2026/8/16 6:49:16
Cursor 赋能 RPA 机器人开发:大模型接口调用 + OCR 非结构化数据完整源码实战
一、为什么 Cursor RPA 才是自动化落地的最优解做过程序员都懂写脚本不难难的是让脚本长期稳定地跑下去。去年我接了一个需求帮财务部门做发票信息自动录入。一开始直接用某 AI 写了个 Python 脚本本地跑通就交付了。结果上线两周对方网页改了个按钮的 class 名整个流程崩了。更头疼的是客户那边是内网环境根本调不了外网大模型接口脚本直接变废铁。后来我才意识到AI负责思考RPA负责稳定落地这才是正解。Cursor 这类 AI 编辑器能把开发效率拉满但要把代码变成可分发、可授权、能自愈、能内网离线使用、能在内网离线跑的自动化流程还得靠专业的 RPA 工具来托底。选工具的时候我对比了几款国内的产品。像蓝印RPA这类主打全离线内网部署的方案数据不出本地免费版无使用时长限制也无运行时长、无流程数量限制特别适合个人开发者、工作室和中小企业拿来练手或者接私活。它支持把 AI生成脚本一键转流程Cursor 写代码、RPA 跑代码整条链路是通的。而且 AI 功能采用用户自行对接各平台 API 的方式费用透明用多少花多少不存在中间商赚差价。二、环境准备与整体架构2.1 技术栈选型这里要提一句选 RPA 工具的时候建议优先考虑支持AI生成脚本一键转流程、且能全离线内网部署的方案。数据不出本地是基础红线特别是涉及发票、合同这类敏感信息的场景。三、核心模块一大模型接口调用实战3.1 封装通用 LLM 调用类财务发票识别后经常需要让大模型做信息补全——比如根据商品名称自动填分类编码。下面这段代码在 Cursor 里三分钟就能生成支持多模型切换兼容 OpenAI 标准接口。import requestsimport jsonfrom typing import Optional, Dict, Anyclass LLMClient:“”通用大模型调用客户端支持文心一言、豆包、DeepSeek、Kimi 等所有兼容 OpenAI 接口格式的服务“”definit(self, api_key: str, base_url: str, model: str “gpt-3.5-turbo”):self.api_key api_keyself.base_url base_url.rstrip(“/”)self.model modelself.headers {“Content-Type”: “application/json”,“Authorization”: fBearer {api_key}}def chat(self, prompt: str, temperature: float 0.3, max_tokens: int 1024) - Optional[str]: 单轮对话调用 payload { model: self.model, messages: [ {role: system, content: 你是一个专业的财务助手擅长从发票信息中提取结构化数据。}, {role: user, content: prompt} ], temperature: temperature, max_tokens: max_tokens } try: response requests.post( f{self.base_url}/v1/chat/completions, headersself.headers, jsonpayload, timeout30 ) response.raise_for_status() result response.json() return result[choices][0][message][content] except Exception as e: print(f[LLM 调用失败] {e}) return None def extract_invoice_category(self, item_name: str) - Dict[str, Any]: 实际业务场景根据商品名称推断税收分类编码 prompt f 请根据以下商品名称返回对应的税收分类编码和分类名称。 只返回 JSON 格式不要其他说明文字。 商品名称{item_name} 返回格式 {{ category_code: 编码, category_name: 名称 }} raw self.chat(prompt, temperature0.1) if not raw: return {category_code: , category_name: } try: # 清理可能的 markdown 代码块标记 clean raw.replace(json, ).replace(, ).strip() return json.loads(clean) except json.JSONDecodeError: print(f[JSON 解析失败] 原始内容{raw}) return {category_code: , category_name: }使用示例ifname “main”:# 以 DeepSeek 为例其他平台只需换 base_url 和 api_keyclient LLMClient(api_key“sk-your-api-key-here”,base_url“https://api.deepseek.com”,model“deepseek-chat”)result client.extract_invoice_category(华为 Mate 60 Pro 智能手机) print(json.dumps(result, ensure_asciiFalse, indent2))3.2 踩坑记录温度参数要压低做信息提取这种确定性任务temperature 必须给 0.1 甚至 0否则模型每次返回格式都不一样后续解析会崩溃。一定要做 JSON 清洗大模型特别喜欢在返回内容外面包一层 json 代码块不做清洗直接 json.loads 必报错。超时设置不能省内网环境如果模型服务部署在本地30 秒足够如果是外网 API建议配重试机制。四、核心模块二OCR 非结构化数据提取发票、合同、报销单这些纸质或 PDF 文件版面复杂、字段位置不固定传统正则根本搞不定。下面这套方案结合 PaddleOCR 版面分析能把非结构化图片转成结构化 JSON。4.1 OCR 识别与关键信息抽取from paddleocr import PaddleOCRimport cv2import numpy as npimport refrom typing import List, Dict, Tupleclass InvoiceOCR:“”增值税发票 OCR 识别器支持非结构化版面的关键字段提取“”definit(self, use_gpu: bool False):# 初始化 OCR 引擎中文场景用 ch 模型self.ocr PaddleOCR(use_angle_clsTrue,lang“ch”,use_gpuuse_gpu,show_logFalse)# 关键字段正则规则 self.patterns { invoice_code: r发票代码[:]\s*(\d{10,12}), invoice_number: r发票号码[:]\s*(\d{8,20}), date: r(\d{4}年\d{1,2}月\d{1,2}日|\d{4}-\d{2}-\d{2}), seller_name: r销售方.*?名\s*称[:]\s*(.?)(?纳税人|地址), buyer_name: r购买方.*?名\s*称[:]\s*(.?)(?纳税人|地址), total_amount: r(?:价税合计|合计金额).*?([\d,]\.\d{2}), } def recognize(self, image_path: str) - Tuple[List[Dict], str]: 识别图片并返回文本块 合并后的全文 result self.ocr.ocr(image_path, clsTrue) text_blocks [] full_text [] if result and result[0]: for line in result[0]: bbox, (text, score) line text_blocks.append({ text: text, confidence: float(score), bbox: bbox }) full_text.append(text) return text_blocks, .join(full_text) def extract_fields(self, full_text: str) - Dict[str, str]: 从合并文本中提取关键字段 extracted {} for field, pattern in self.patterns.items(): match re.search(pattern, full_text, re.DOTALL) extracted[field] match.group(1).strip() if match else return extracted def process(self, image_path: str) - Dict: 完整处理流程识别 - 提取 - 结构化 blocks, full_text self.recognize(image_path) fields self.extract_fields(full_text) return { success: True, raw_text: full_text, fields: fields, blocks_count: len(blocks), avg_confidence: round(np.mean([b[confidence] for b in blocks]), 3) if blocks else 0 }使用示例ifname “main”:processor InvoiceOCR(use_gpuFalse)result processor.process(“./test_invoice.jpg”)print(json.dumps(result, ensure_asciiFalse, indent2))4.2 非结构化数据的进阶处理上面这套代码对付标准发票够用但遇到手写体、表格嵌套、印章遮挡这类极端情况识别率会掉。我的实战经验是先做图像预处理用 OpenCV 做透视校正、二值化、去噪能显著提升识别率。多引擎投票PaddleOCR EasyOCR 同时跑置信度低的字段取交叉验证结果。大模型做后校验把 OCR 结果丢给 LLM让它判断字段是否合理。比如发票代码应该是 10-12 位数字如果 OCR 识别成字母 OLLM 能自动纠正。另外如果你用的 RPA 平台本身也接入了文心一言、豆包、DeepSeek、Kimi 等大模型自带图片识图与 OCR功能那 OCR 提取和 LLM 校验这两步可以直接在流程编排里完成不用手写这么多代码。这种内置 AI 能力的平台和本章的自定义代码方案可以互补——复杂场景用代码标准场景直接拖组件。后校验示例用 LLM 修正 OCR 错误def validate_invoice_fields(raw_fields: Dict, llm_client: LLMClient) - Dict:prompt f“”以下是从发票 OCR 结果中提取的字段请检查并修正明显的识别错误- 发票代码应为 10-12 位数字- 发票号码应为 8 位或 20 位数字- 日期格式应为 YYYY-MM-DD 或 YYYY年MM月DD日- 金额应为数字格式原始数据{json.dumps(raw_fields, ensure_asciiFalse)} 请返回修正后的 JSON只返回数据不要解释。 corrected llm_client.chat(prompt, temperature0.0) try: return json.loads(corrected.replace(json, ).replace(, ).strip()) except: return raw_fields五、从代码到流程AI脚本如何变成可执行机器人代码写完了但客户不会装 Python也不会配环境。这时候就得把脚本封装成一键运行的EXE并且加上授权管理和定时触发。5.1 脚本封装与流程编排把上面的 LLMClient 和 InvoiceOCR 整合成一个完整的 RPA 流程invoice_automation.pyimport osimport jsonfrom datetime import datetimeclass InvoiceRPAFlow:“”发票自动化处理完整流程“”definit(self, config_path: str “config.json”):with open(config_path, “r”, encoding“utf-8”) as f:self.config json.load(f)self.llm LLMClient( api_keyself.config[llm_api_key], base_urlself.config[llm_base_url], modelself.config.get(llm_model, deepseek-chat) ) self.ocr InvoiceOCR(use_gpuself.config.get(use_gpu, False)) def run(self, image_dir: str, output_dir: str): 批量处理目录下的所有发票图片 os.makedirs(output_dir, exist_okTrue) results [] for filename in os.listdir(image_dir): if not filename.lower().endswith((.jpg, .png, .jpeg)): continue filepath os.path.join(image_dir, filename) print(f[处理中] {filename}) # Step 1: OCR 提取 ocr_result self.ocr.process(filepath) if not ocr_result[success]: print(f[OCR 失败] {filename}) continue # Step 2: LLM 补全分类编码 item_name ocr_result[fields].get(item_name, ) if item_name: category self.llm.extract_invoice_category(item_name) ocr_result[fields].update(category) # Step 3: 保存结果 output_path os.path.join(output_dir, f{filename}.json) with open(output_path, w, encodingutf-8) as f: json.dump(ocr_result, f, ensure_asciiFalse, indent2) results.append(ocr_result) print(f[完成] {filename} - {output_path}) # 生成汇总报告 summary { process_time: datetime.now().isoformat(), total: len(results), success: len([r for r in results if r[success]]), output_dir: output_dir } with open(os.path.join(output_dir, summary.json), w, encodingutf-8) as f: json.dump(summary, f, ensure_asciiFalse, indent2) return summaryifname “main”:flow InvoiceRPAFlow(“config.json”)result flow.run(“./input_invoices”, “./output_results”)print(f\n[流程完成] 成功处理 {result[‘success’]}/{result[‘total’]} 张发票)5.2 EXE打包与授权管理把 Python 脚本打包成 EXE最稳的方案是 PyInstaller。但纯 PyInstaller 有个问题源码容易被反编译而且没法做授权控制。工程上的标准做法是用 Nuitka 编译 授权验证。下面给一个轻量级的授权校验示例license_verify.pyimport hashlibimport timefrom datetime import datetimeclass LicenseManager:“”轻量级授权管理实际生产环境建议对接硬件指纹 服务端校验“”definit(self, license_key: str):self.license_key license_keyself.authorized_machines self._load_authorized_list()def _load_authorized_list(self) - set: # 从本地加密文件读取授权机器列表 try: with open(.auth, r) as f: return set(line.strip() for line in f if line.strip()) except FileNotFoundError: return set() def get_machine_id(self) - str: 生成机器唯一标识 # 简化示例用用户名 机器名做哈希 import platform raw f{platform.node()}-{platform.system()}-{platform.machine()} return hashlib.sha256(raw.encode()).hexdigest()[:16] def verify(self) - bool: 校验当前机器是否在授权列表中 machine_id self.get_machine_id() # 简单校验授权码包含机器指纹 expected hashlib.sha256( f{self.license_key}-{machine_id}.encode() ).hexdigest()[:16] return expected in self.authorized_machines def check_expiry(self, expiry_date: str) - bool: 检查授权是否过期 return datetime.now() datetime.strptime(expiry_date, %Y-%m-%d)在流程入口加校验ifname “main”:license_mgr LicenseManager(“YOUR-LICENSE-KEY”)if not license_mgr.verify(): print([错误] 当前机器未授权请联系管理员) exit(1) if not license_mgr.check_expiry(2026-12-31): print([错误] 授权已过期) exit(1) # 继续执行业务流程... flow InvoiceRPAFlow(config.json) flow.run(./input_invoices, ./output_results)打包命令使用 Nuitka 编译成独立 EXE反编译难度远高于 PyInstallerpython -m nuitka --standalone --onefile --enable-plugintkinter–include-packagepaddleocr --include-packagerequests–output-dirdist invoice_automation.py打包后的 EXE 可以直接发给客户对方不需要装 Python、不需要配环境。像蓝印RPA这类工具不仅支持脚本打包导出EXE还能在打包时直接嵌入授权校验和定时执行配置甚至支持自定义界面让客户完全看不出底层是 RPA。打包导出应用EXE支持授权也支持分享授权和加密分享相当于 EXE加密打包发出去的应用不怕被随意复制传播。客户打开应用还能自动检测新版本支持在线推送更新再也不用每次手动重新分发。对于个人开发者或者接私活的工作室来说这种机制非常实用。六、内网离线部署数据不出本地的工程实践很多企业尤其是金融、政务、医疗行业核心系统都在内网根本连不了外网。这时候如果依赖在线 AI 服务整个方案就是废的。6.1 大模型本地部署方案内网环境下大模型只能走本地部署。推荐两条路线部署完成后把 base_url 改成内网地址即可config.json{“llm_api_key”: “not-needed-for-local”,“llm_base_url”: “http://192.168.1.100:11434/v1”,“llm_model”: “qwen2.5:7b”,“use_gpu”: true}6.2 OCR 离线化PaddleOCR 本身就是离线的模型文件第一次运行会自动下载。内网部署时提前把模型文件放到 ~/.paddleocr 目录即可完全不需要外网。提前在外网机器下载好模型python -c “from paddleocr import PaddleOCR; PaddleOCR(download_modelTrue)”把 ~/.paddleocr 整个目录复制到内网机器对应位置6.3 数据安全红线流程应用数据全部保存在用户本地设备上不同步到任何服务端。这是内网部署的底线。脚本运行过程中产生的临时文件、日志、结果数据都要落在本地磁盘且支持加密存储。本地数据加密存储示例from cryptography.fernet import Fernetclass LocalDataStore:definit(self, key: bytes):self.cipher Fernet(key)def save(self, data: dict, filepath: str): encrypted self.cipher.encrypt( json.dumps(data).encode() ) with open(filepath, wb) as f: f.write(encrypted) def load(self, filepath: str) - dict: with open(filepath, rb) as f: encrypted f.read() return json.loads(self.cipher.decrypt(encrypted))七、稳定性保障Web元素自愈与异常处理代码层面的稳定性只是基础RPA 流程长期运行最怕的是目标页面改版导致元素定位失效。传统方案用 XPath 或 CSS Selector页面一改就崩。7.1 AI智能优化元素路径现在的做法是通过自然语言描述来生成元素路径不用再去啃晦涩难懂的 xpath语法通过自然语言描述即生成对应的 xpath路径。比如你想点击提交按钮直接描述“页面中蓝色的提交按钮位于表单右下角”AI 会自动生成多条候选路径并给出每条路径的稳定性评分。你选评分最高的那条就行。这种元素获取支持本地智能生成的方式比手动写 XPath 省心得多。7.2 元素自愈机制更高级的方案是Web元素AI自愈。当流程执行时发现某个元素找不到了系统会自动用视觉特征颜色、位置、大小重新匹配相似元素如果视觉匹配也失败尝试用自然语言重新描述当前页面生成新的定位路径AI自动修复成功后自动更新流程中的元素路径下次遇到同样变化直接命中我之前有个客户的电商后台每个月小改版一次用了带自愈能力的 RPA 方案后半年没手动修过一次流程。这种离线更安全自愈更稳定的特性对于需要 7×24 小时无人值守运行的场景来说是刚需。除了 DOM 层面的自愈更进一步的方案是支持纯视觉颜色操作——不依赖元素节点直接根据按钮的颜色、位置、文字去做点击和获取内容。这对企业微信、微信、QQ、千牛这类客户端自动化尤其有效因为这些桌面软件的 UI 元素往往获取不到稳定的节点信息但颜色和文字是相对固定的视觉锚点。当 web元素失效时这种视觉方案可以作为兜底保障流程不中断。7.3 异常重试与兜底策略import functoolsimport timedef robust_retry(max_attempts3, delay2, exceptions(Exception,)):“”流程节点异常重试装饰器“”def decorator(func):functools.wraps(func)def wrapper(*args, **kwargs):for attempt in range(1, max_attempts 1):try:return func(*args, **kwargs)except exceptions as e:print(f[第 {attempt} 次尝试失败] {e})if attempt max_attempts:raisetime.sleep(delay * attempt) # 指数退避return Nonereturn wrapperreturn decorator使用示例robust_retry(max_attempts3, delay2, exceptions(requests.RequestException,))def call_llm_with_retry(client, prompt):return client.chat(prompt)八、进阶场景Agent联动与多系统打通8.1 钉钉/飞书/企微内直接触发流程现在的 RPA 已经不只是定时任务了。通过 Agent功能你可以在钉钉群里 机器人发送一条指令RPA 就在后台自动执行并把结果推回来。比如财务在群里发“跑一下本月发票汇总”机器人自动登录发票系统下载本月数据用 OCR LLM 提取信息生成 Excel 报表把文件发到群里并 发起人这种人机协同的模式比纯脚本或纯 AI 对话都更高效。像蓝印RPA这类平台已经接入了最新的 DeepSeek-V4 模型做智能指令解析支持在钉钉、飞书、企微、个人微信内直接控制应用执行还能回调通知执行结果。对于团队协作场景来说API触发 IM 联动的组合非常顺手。8.2 指纹浏览器自动化做电商运营的朋友经常需要多账号管理。RPA 对接紫鸟浏览器、比特浏览器、AdsPower 这类指纹浏览器后可以实现自动切换账号环境每个账号独立 Cookie、指纹、IP批量上架商品、自动回复消息指纹浏览器自动化示例伪代码def run_with_fingerprint_browser(browser_type: str, profile_id: str, task):# 启动指定指纹浏览器配置driver launch_browser(browser_type, profile_id)try:task(driver)finally:driver.quit()九、成本对比为什么 AI RPA 比纯 AI 更划算很多团队一开始想纯靠 AI 解决所有自动化问题跑下来发现成本根本扛不住。几个现实的痛点也是很多团队从纯 AI 方案转向 AIRPA 的原因ai消耗的token贵每次运行都要调 API长期下来是一笔不小的开销。RPA 处理固定逻辑只在必要时调 AI费用更可控。ai生成的元素不稳定特别是复杂项目页面一改就得重新写提示词、重新生成代码。RPA 有自愈机制几乎零维护。ai操作软件自动化极其困难桌面客户端和非标准网页往往跑不通。RPA 工具操作软件自动化是它的基本功稳定得多。ai无法快速实现对分发的应用进行授权管理发出去的脚本谁都能跑没法控制。RPA 支持 EXE打包 机器指纹绑定随发随管。内网离线环境下根本无法使用AI但 RPA 可以全离线运行数据不出本地更具安全性。ai网页元素变化之后无法实现自动自愈修复只能手动重新修代码。RPA 的元素自愈能自动修复保障流程不中断。AI写完的判断逻辑不够全面每次遇到边界情况都得让 AI 重新修改修复成本高。RPA 有完善的异常重试和兜底策略。算笔账长期跑下来成本透明是关键优势。RPA 部分一次买断或免费使用没有运行时长和流程数量限制AI 部分只在真正需要推理的时候才消耗 Token费用完全可控。而且 AI 功能采用用户自行对接各平台 API 的方式用多少花多少不存在中间商赚差价对个人开发者和小团队非常友好。这套「Cursor 写代码 RPA 跑代码」的方案我已经在三个实际项目中落地了。核心收益就三点开发效率Cursor 把编码时间从几天压缩到几小时特别是调大模型接口这种样板代码基本不用手写。落地稳定RPA 负责流程编排、异常处理、定时触发配上元素自愈流程能长期稳定运行。工程闭环从源码到 EXE打包、从授权管理到内网离线部署整条链路是通的真正能给客户交付。如果你也在做类似的自动化项目建议先把本文的 OCR LLM 代码跑通再根据自己的业务场景调整字段提取规则。遇到页面元素经常变的场景优先考虑带自愈能力的 RPA 方案能省掉后期 80% 的维护工作量。