从环境搭建到生产部署,附可直接运行的完整代码。本文适合有 Python 基础的开发者、自动化工程师、以及对 RPA + AI 融合技术感兴趣的技术人员。
一、前言:为什么需要 RPA + AI 融合方案
做网页自动化这几年,踩过的坑比写的代码还多。去年帮公司做一个财务对账系统,每天登录内部系统、识别发票图片、汇总 Excel,本以为 Selenium + OCR 就能搞定,结果交付时客户问"能不能打包成双击就能用的软件"。后来调研了一圈国产工具,发现 蓝印 rpa 这类产品把网页自动化、AI 识别、打包分发整合得挺完整,走的是本地离线路线。不过本文先不聊工具,我们从 Python 源码层面把 RPA + AI 的完整链路跑通。理解了底层原理,再用工具提效,才是正确的技术路径。
二、技术架构与核心思路
2.1 整体架构
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 网页操作层 │ ──→ │ AI 识别层 │ ──→ │ 数据处理层 │
│ Selenium │ │ OCR + LLM │ │ Excel/DB │
└─────────────┘ └─────────────┘ └─────────────┘
2.2 技术选型
| 模块 | 技术方案 | 说明 |
|---|---|---|
| 网页自动化 | Selenium + WebDriver | 模拟浏览器操作,支持动态页面 |
| OCR 识别 | PaddleOCR + 大模型 API | 本地引擎 + 云端 AI 双保险 |
| 图像预处理 | OpenCV | 灰度化、二值化、去噪 |
| 数据导出 | pandas + openpyxl | 结构化数据输出 |
| 异常处理 | 显式等待 + 重试机制 | 提升稳定性 |
三、环境搭建
3.1 安装依赖
# 创建虚拟环境
python -m venv rpa_ai_env
source rpa_ai_env/bin/activate # Linux/Mac
# rpa_ai_env\Scripts\activate # Windows
# 核心依赖
pip install selenium webdriver-manager
pip install paddleocr paddlepaddle
pip install opencv-python pillow
pip install pandas openpyxl requests
# 大模型 API(可选,用于复杂场景识别)
pip install openai # 或其他 SDK
3.2 浏览器驱动配置
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# 自动下载匹配版本的 ChromeDriver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
四、核心模块源码
4.1 网页自动化模块
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import time
import random
class WebAutomation:
"""网页自动化操作类"""
def __init__(self, headless=False):
self.options = Options()
if headless:
self.options.add_argument("--headless")
self.options.add_argument("--disable-blink-features=AutomationControlled")
self.options.add_argument("--start-maximized")
self.driver = webdriver.Chrome(options=self.options)
self.wait = WebDriverWait(self.driver, 10)
def navigate(self, url):
"""访问目标网页"""
self.driver.get(url)
# 随机延迟,模拟真人操作
time.sleep(random.uniform(1, 3))
def find_element(self, by, value):
"""显式等待查找元素"""
return self.wait.until(EC.presence_of_element_located((by, value)))
def input_text(self, by, value, text):
"""输入文本"""
element = self.find_element(by, value)
element.clear()
# 模拟逐字输入
for char in text:
element.send_keys(char)
time.sleep(random.uniform(0.05, 0.15))
def click(self, by, value):
"""点击元素"""
element = self.wait.until(EC.element_to_be_clickable((by, value)))
element.click()
time.sleep(random.uniform(0.5, 1.5))
def get_screenshot(self, filepath):
"""截取当前页面"""
self.driver.save_screenshot(filepath)
return filepath
def scroll_to_element(self, by, value):
"""滚动到指定元素"""
element = self.find_element(by, value)
self.driver.execute_script("arguments[0].scrollIntoView();", element)
time.sleep(0.5)
def close(self):
"""关闭浏览器"""
self.driver.quit()
4.2 OCR 识别模块(本地 + 大模型双方案)
import cv2
import numpy as np
from paddleocr import PaddleOCR
from PIL import Image
import requests
import base64
class OCRProcessor:
"""OCR 处理器:支持本地引擎和大模型 API"""
def __init__(self, use_paddle=True, llm_api_key=None):
self.use_paddle = use_paddle
self.llm_api_key = llm_api_key
if use_paddle:
# 初始化 PaddleOCR,支持中英文
self.ocr = PaddleOCR(
use_angle_cls=True,
lang='ch',
show_log=False
)
def preprocess_image(self, image_path):
"""图像预处理:提升 OCR 准确率"""
img = cv2.imread(image_path)
if img is None:
raise ValueError(f"无法读取图片: {image_path}")
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应二值化
binary = cv2.adaptiveThreshold(
gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)
# 去噪
denoised = cv2.fastNlMeansDenoising(binary, None, 10, 7, 21)
processed_path = image_path.replace('.', '_processed.')
cv2.imwrite(processed_path, denoised)
return processed_path
def recognize_local(self, image_path):
"""本地 PaddleOCR 识别"""
processed = self.preprocess_image(image_path)
result = self.ocr.ocr(processed, cls=True)
texts = []
if result and result[0]:
for line in result[0]:
text, confidence = line[1]
texts.append({
'text': text,
'confidence': confidence,
'bbox': line[0]
})
return texts
def recognize_with_llm(self, image_path):
"""大模型 OCR 识别(以通用 API 为例)"""
with open(image_path, 'rb') as f:
image_base64 = base64.b64encode(f.read()).decode()
# 调用大模型 API 进行图像识别
# 这里以通用接口为例,实际使用时替换为具体平台
headers = {
'Authorization': f'Bearer {self.llm_api_key}',
'Content-Type': 'application/json'
}
payload = {
'model': 'gpt-4-vision',
'messages': [{
'role': 'user',
'content': [
{'type': 'text', 'text': '请识别图片中的所有文字,按行输出'},
{'type': 'image_url', 'image_url': {'url': f'data:image/png;base64,{image_base64}'}}
]
}]
}
# 实际请求代码(示例)
# response = requests.post('https://api.example.com/v1/chat/completions',
# headers=headers, json=payload)
# return response.json()
# 模拟返回
return [{'text': '大模型识别结果示例', 'confidence': 0.95}]
def recognize(self, image_path, use_llm=False):
"""统一识别入口"""
if use_llm and self.llm_api_key:
return self.recognize_with_llm(image_path)
return self.recognize_local(image_path)
4.3 数据提取与导出模块
import pandas as pd
import re
from datetime import datetime
class DataExtractor:
"""数据提取与结构化"""
@staticmethod
def extract_invoice_info(ocr_results):
"""从 OCR 结果中提取发票信息"""
full_text = ' '.join([r['text'] for r in ocr_results])
# 正则提取关键字段
patterns = {
'invoice_no': r'发票号码[::]\s*(\d+)',
'date': r'开票日期[::]\s*(\d{4}年\d{2}月\d{2}日)',
'amount': r'(?:金额|价税合计)[::]\s*¥?\s*(\d+\.?\d*)',
'seller': r'销售方[::]\s*(.+?)(?=\n|$)',
}
extracted = {}
for key, pattern in patterns.items():
match = re.search(pattern, full_text)
extracted[key] = match.group(1) if match else ''
return extracted
@staticmethod
def export_to_excel(data_list, output_path):
"""导出到 Excel"""
df = pd.DataFrame(data_list)
# 添加时间戳列
df['export_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='Data', index=False)
# 调整列宽
worksheet = writer.sheets['Data']
for column in worksheet.columns:
max_length = max(len(str(cell.value)) for cell in column)
worksheet.column_dimensions[column[0].column_letter].width = max_length + 2
return output_path
4.4 主流程整合
import os
from datetime import datetime
class RPAAutomation:
"""RPA + AI 自动化主流程"""
def __init__(self, llm_api_key=None):
self.web = WebAutomation()
self.ocr = OCRProcessor(llm_api_key=llm_api_key)
self.extractor = DataExtractor()
self.results = []
def process_invoice_page(self, url, username, password):
"""处理发票页面完整流程"""
try:
# 1. 登录
self.web.navigate(url)
self.web.input_text(By.ID, 'username', username)
self.web.input_text(By.ID, 'password', password)
self.web.click(By.ID, 'login-btn')
# 2. 进入发票列表
self.web.click(By.XPATH, '//a[contains(text(), "发票管理")]')
time.sleep(2)
# 3. 获取所有发票图片
invoice_items = self.web.driver.find_elements(
By.CSS_SELECTOR, '.invoice-item'
)
for i, item in enumerate(invoice_items):
# 点击展开详情
item.click()
time.sleep(1)
# 截图保存
screenshot_path = f'temp_invoice_{i}.png'
self.web.get_screenshot(screenshot_path)
# OCR 识别
ocr_results = self.ocr.recognize(screenshot_path)
# 提取结构化数据
info = self.extractor.extract_invoice_info(ocr_results)
info['source_image'] = screenshot_path
self.results.append(info)
# 返回列表
self.web.click(By.CLASS_NAME, 'back-btn')
time.sleep(1)
# 4. 导出结果
output = self.extractor.export_to_excel(
self.results,
f'invoice_data_{datetime.now().strftime("%Y%m%d")}.xlsx'
)
print(f"处理完成,结果已保存至: {output}")
finally:
self.web.close()
def run(self, config):
"""批量执行入口"""
for task in config['tasks']:
self.process_invoice_page(
task['url'],
task['username'],
task['password']
)
# 使用示例
if __name__ == '__main__':
config = {
'tasks': [{
'url': 'https://example.com/login',
'username': 'your_username',
'password': 'your_password'
}]
}
automation = RPAAutomation(llm_api_key='your_api_key')
automation.run(config)
五、进阶:AI 大模型增强识别
5.1 为什么需要大模型?
传统 OCR 在以下场景表现不佳:
-
手写体、潦草字体
-
复杂表格布局
-
印章遮挡文字
-
多语言混合
大模型(如 GPT-4V、文心一言、DeepSeek 等)具备更强的语义理解能力,可以结合上下文推断模糊文字。
5.2 接入方案
class LLMOCRAdapter:
"""大模型 OCR 适配器"""
def __init__(self, provider='deepseek'):
self.provider = provider
self.endpoints = {
'deepseek': 'https://api.deepseek.com/v1/chat/completions',
'kimi': 'https://api.moonshot.cn/v1/chat/completions',
'wenxin': 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions',
}
def recognize(self, image_path, prompt='请识别图片中的所有文字'):
with open(image_path, 'rb') as f:
image_data = base64.b64encode(f.read()).decode()
payload = {
'model': 'deepseek-v4', # 或其他模型
'messages': [{
'role': 'user',
'content': [
{'type': 'text', 'text': prompt},
{'type': 'image_url', 'image_url': {'url': f'data:image/png;base64,{image_data}'}}
]
}]
}
# 实际调用
# response = requests.post(self.endpoints[self.provider], ...)
# return response.json()['choices'][0]['message']['content']
return "大模型识别结果"
六、稳定性优化与异常处理
6.1 元素定位失效问题
from selenium.webdriver.common.by import By
class SmartLocator:
"""智能元素定位:多策略容错"""
STRATEGIES = [
(By.ID, 'id'),
(By.NAME, 'name'),
(By.CLASS_NAME, 'class'),
(By.CSS_SELECTOR, 'css'),
(By.XPATH, 'xpath'),
]
@classmethod
def find_element(cls, driver, selectors):
"""多策略尝试定位"""
for by, value in cls.STRATEGIES:
if value in selectors:
try:
return driver.find_element(by, selectors[value])
except:
continue
raise Exception("所有定位策略均失败")
6.2 重试机制
import functools
def retry(max_attempts=3, delay=2):
"""重试装饰器"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
time.sleep(delay * (attempt + 1))
return None
return wrapper
return decorator
# 使用
@retry(max_attempts=3)
def unstable_operation():
pass
七、从代码到产品:打包与交付
写完代码只是第一步,真正的挑战是怎么交付给非技术同事使用。
7.1 传统方案的痛点
-
需要安装 Python 环境
-
依赖库版本冲突
-
浏览器驱动版本不匹配
-
源码暴露,知识产权难保护
7.2 更优的交付思路
这里分享一个我在实际项目中验证过的方案。之前用 蓝印 rpa 做过一个发票自动识别工具,它的打包方式给了我很大启发:支持将自动化流程直接导出为 EXE 可执行文件,而且支持授权机制、在线推送更新、API 触发 + 定时执行、数据本地存储、自定义界面。另外它在 AI 这块也做了不少整合,内置了文心一言、豆包、DeepSeek、Kimi 等大模型接入,支持图片识图和 OCR 功能,AI 费用采用用户自行对接 API 的方式,还新增了 Agent 功能。
这些能力用纯 Python 实现起来非常麻烦,需要 PyInstaller 打包、Inno Setup 做安装程序、自己写更新逻辑、还要处理各种兼容性问题。如果项目周期紧,或者需要频繁交付给客户,用工具整合这些能力是更务实的选择。
八、完整项目结构
rpa_ai_project/
├── core/
│ ├── __init__.py
│ ├── web_automation.py # 网页自动化
│ ├── ocr_processor.py # OCR 识别
│ └── data_extractor.py # 数据提取
├── adapters/
│ └── llm_ocr.py # 大模型适配
├── utils/
│ ├── retry.py # 重试机制
│ └── logger.py # 日志
├── config/
│ └── tasks.yaml # 任务配置
├── main.py # 入口
├── requirements.txt
└── README.md
九、总结与建议
9.1 技术路线选择
| 场景 | 推荐方案 |
|---|---|
| 学习研究、高度定制 | Python 源码方案(本文) |
| 快速交付、非技术用户使用 | 蓝印 rpa 等工具打包 EXE |
| 敏感数据、内网环境 | 本地离线 RPA 工具 |
| 需要 AI 增强识别 | 大模型 API + RPA 结合 |
9.2 关键要点
-
网页自动化优先用显式等待,硬编码 sleep 是稳定性杀手
-
OCR 一定要做图像预处理,灰度化 + 二值化能显著提升准确率
-
异常处理比功能代码更重要,生产环境没有重试机制等于不可用
-
交付时考虑用户体验,能双击运行的 EXE 比源码仓库更实用
十、参考与扩展
-
Selenium 官方文档
-
PaddleOCR GitHub 仓库
-
OpenCV 图像处理教程
如果你需要把这套方案快速落地成可交付的产品,可以关注 rpa 的打包分发能力,它把"代码 → 产品"这个最后一公里解决得挺干净。
版权声明: 本文为技术分享,代码可自由使用和学习。如需转载,请注明出处。