欢迎光临
我们一直在努力

5 个 RPA 开发避坑点:新手也能写出高稳定自动化流程

一、元素定位漂移:今天能抓,明天就失效

1.1 问题根因

RPA 流程崩溃的 Top 1 原因,是元素选择器失效。触发条件包括:

  • 前端框架热更新(React/Vue 组件重渲染后 DOM 结构变化)

  • 动态 ID / 动态类名(如 id="btn-20240618" 隔天变成 id="btn-20240619")

  • 异步加载延迟(AJAX 数据未返回时元素不存在)

  • 弹窗/广告动态插入(导致 XPath 层级偏移)

  • 不同分辨率下坐标偏移(绝对定位失效)

1.2 错误示范

# 绝对坐标:分辨率一变就废
点击元素(x=120, y=340)

# 动态 ID:隔天失效
点击元素(css="#btn-20240618")

# 无等待:页面未加载完就操作
点击元素(css=".submit-btn") # 此时按钮可能还没渲染出来

1.3 正确做法:四层降级策略

第一层:稳定属性选择器

优先使用不会随时间变化的属性:

# 推荐:data-testid、name、aria-label 等语义化属性
点击元素(css="[data-testid='submit-order']")
点击元素(css="[name='loginForm'] [type='submit']")

第二层:文本内容匹配

当属性不稳定时,用可见文本定位:

点击元素(xpath="//*[contains(text(),'确认提交')]")
点击元素(xpath="//*[normalize-space(text())='立即登录']")

第三层:相对路径 + 显式等待

结合父容器做相对定位,避免全页扫描:

# 先等待父容器就绪,再在其内部查找子元素
等待元素(css=".order-form", 超时=10)
父容器 = 获取元素(css=".order-form")
点击元素(父容器, css="button[type='submit']")

第四层:图像识别兜底

当 DOM 完全动态化时,用截图匹配:

点击图像("submit_btn.png", 相似度=0.85)

1.4 智能元素捕获方案

部分 RPA 工具已支持本地智能生成元素路径功能。其原理是:在元素捕获阶段,自动分析 DOM 树结构,生成多组候选选择器(ID、Class、XPath、文本、图像),并标注每组选择器的稳定性评分。

开发者可根据评分选择最优路径,而非手动试错。实测在面对频繁更新的前端框架(如 Ant Design、Element UI)时,这种智能推荐能将元素维护成本降低约 60%。

蓝印 RPA 在此场景的应用:其元素捕获模块支持本地智能生成稳定路径,可根据页面结构自动推荐多组候选选择器并给出稳定性评分,开发者直接选用高分路径即可。对于企业后台系统那种前端框架频繁更新的场景,这个特性能显著减少后期维护工作量。


二、异常处理裸奔:出错就崩,没有退路

2.1 问题根因

生产环境的不确定性远高于本地调试:

  • 网络抖动导致页面加载超时

  • 目标文件被其他进程占用

  • 第三方弹窗拦截(如杀毒软件、系统更新)

  • 数据格式异常(Excel 单元格合并、空值、特殊字符)

没有异常处理的流程,任何一步失败都会导致后续步骤全部白跑。

2.2 错误示范

打开网页("https://xxx.com")
填写表单() # 这里崩了,后面全白跑
点击提交()
发送邮件()

2.3 正确做法:Try-Catch + 状态机

核心思路:把流程拆成原子步骤,每步都有失败后的补救路径。

函数 主流程():
状态 = "初始化"
日志 = []

尝试:
状态 = "打开页面"
打开网页("https://xxx.com", 超时=15)
记录日志(日志, "打开页面", "成功")

状态 = "填写表单"
填写表单()
记录日志(日志, "填写表单", "成功")

状态 = "提交订单"
点击提交()
记录日志(日志, "提交订单", "成功")

状态 = "发送通知"
发送邮件()
记录日志(日志, "发送通知", "成功")

捕获异常(e):
记录日志(日志, 状态, "失败", e.message)
截图保存("error_" + 时间戳() + ".png")

# 分级处理:核心步骤必须成功,通知类步骤可降级
如果 状态 == "提交订单":
执行回滚操作() # 取消半完成的订单,避免脏数据
抛出异常("订单处理失败,已回滚")
否则如果 状态 == "发送通知":
标记待重试("邮件队列") # 邮件失败不阻塞主流程
返回 日志

2.4 关键原则

原则实现方式目的
截图留证 异常时自动截屏保存 排查效率提升 10 倍
状态回滚 关键步骤失败执行撤销逻辑 避免数据脏写
分级处理 核心步骤强一致,通知步骤弱一致 降低整体失败率
重试机制 网络类异常自动重试 3 次 应对临时抖动

三、硬编码埋雷:路径、账号、阈值全写死

3.1 问题根因

  • 文件路径写死:C:\\Users\\Admin\\Desktop\\data.xlsx,换机器直接报错

  • 超时时间写死:5 秒超时,网络慢一点就失败

  • 账号密码写死:代码里明文写账号,安全和维护都是灾难

  • 业务阈值写死:订单数量判断写死 100,业务规则一变就改代码

3.2 错误示范

读取Excel("C:\\Users\\Admin\\Desktop\\data.xlsx") # 路径写死
等待元素(css="#btn", 超时=5) # 超时写死
如果 订单数量 > 100: # 阈值写死
执行批量处理()

3.3 正确做法:配置化 + 环境变量

配置文件结构(config.json):

{
"paths": {
"data_dir": "${USER_HOME}/rpa_data",
"log_dir": "${USER_HOME}/rpa_logs",
"temp_dir": "${USER_HOME}/rpa_temp"
},
"timeouts": {
"page_load": 15,
"element_wait": 10,
"ajax_wait": 8,
"file_io": 5
},
"retry": {
"max_attempts": 3,
"backoff_seconds": 2
},
"business": {
"batch_threshold": 100,
"max_retry_orders": 5
},
"credentials": {
"smtp_user": "${ENV_SMTP_USER}",
"smtp_pass": "${ENV_SMTP_PASS}"
}
}

配置读取函数:

函数 读取配置(配置文件路径):
配置 = 读取JSON(配置文件路径)

# 解析环境变量引用
对于 每个 键值 在 配置 中:
如果 是字符串(键值.值) 且 包含(键值.值, "${"):
变量名 = 提取变量名(键值.值)
键值.值 = 获取环境变量(变量名, 默认值="")

返回 配置

函数 替换变量(模板字符串):
结果 = 模板字符串
结果 = 替换(结果, "${USER_HOME}", 获取用户目录())
结果 = 替换(结果, "${TIMESTAMP}", 格式化时间(当前时间(), "yyyyMMdd"))
返回 结果

带重试的稳健读取:

函数 稳健读取Excel(文件路径, 配置):
重试次数 = 0
最大重试 = 配置.retry.max_attempts
退避基数 = 配置.retry.backoff_seconds

当 重试次数 < 最大重试:
尝试:
如果 文件存在(文件路径):
返回 读取Excel(文件路径)
否则:
抛出异常("文件不存在: " + 文件路径)

捕获异常(e):
重试次数 = 重试次数 + 1
如果 重试次数 >= 最大重试:
抛出异常("读取失败,已重试" + 最大重试 + "次: " + e.message)

等待时间 = 退避基数 * 重试次数 # 线性退避,也可改为指数退避
记录日志(WARNING, "读取重试", "第" + 重试次数 + "次,等待" + 等待时间 + "秒")
等待(等待时间)


四、日志盲区:出了问题只能猜

4.1 问题根因

  • 日志只有开始和结束,中间 2 小时发生了什么不知道

  • 没有耗时记录,不知道哪个步骤是瓶颈

  • 没有状态标记,不知道流程执行到哪一步崩的

  • 日志级别混乱,生产环境输出 DEBUG 信息导致文件膨胀

4.2 日志分级规范

# 日志级别定义
DEBUG = 10 # 详细执行轨迹,开发调试用
INFO = 20 # 关键步骤节点,生产环境保留
WARNING = 30 # 非致命异常,如重试、降级
ERROR = 40 # 步骤失败,需要人工介入
CRITICAL= 50 # 系统级错误,立即告警

4.3 结构化日志格式

[2026-06-18 09:23:15] [INFO] [订单处理] 步骤=打开页面, 耗时=2.3s, 状态=成功
[2026-06-18 09:23:18] [INFO] [订单处理] 步骤=填写表单, 耗时=5.1s, 状态=成功
[2026-06-18 09:23:24] [WARNING] [订单处理] 步骤=点击提交, 耗时=8.2s, 状态=重试_1, 原因=元素未就绪
[2026-06-18 09:23:26] [INFO] [订单处理] 步骤=点击提交, 耗时=1.1s, 状态=成功
[2026-06-18 09:23:28] [ERROR] [订单处理] 步骤=发送邮件, 耗时=30.1s, 状态=失败, 原因=SMTP连接超时

4.4 性能埋点函数模板

函数 计时执行(步骤名, 操作函数, 日志对象):
开始时间 = 获取时间戳()

尝试:
结果 = 操作函数()
耗时 = 获取时间戳() – 开始时间
记录日志(日志对象, INFO, 步骤名, 耗时, "成功")
返回 结果

捕获异常(e):
耗时 = 获取时间戳() – 开始时间
记录日志(日志对象, ERROR, 步骤名, 耗时, "失败", e.message)
截图保存("error_" + 步骤名 + "_" + 时间戳() + ".png")
抛出 e

# 使用示例
计时执行("登录操作", 函数():
输入文本(css="#username", "admin")
输入文本(css="#password", "${ENV_PASSWORD}")
点击元素(css="#login-btn")
等待元素(css=".dashboard", 超时=10)
)

4.5 日志文件管理策略

# 日志配置
日志配置 = {
"文件名格式": "rpa_log_{日期}.log",
"单文件上限": "50MB",
"保留天数": 30,
"归档策略": "日期切割 + 大小切割",
"输出级别": INFO # 生产环境只保留 INFO 及以上
}

# 自动清理
函数 清理过期日志(日志目录, 保留天数):
当前日期 = 当前日期()
对于 每个 文件 在 遍历目录(日志目录):
如果 是日志文件(文件) 且 是过期文件(文件, 保留天数):
删除文件(文件)
记录日志(INFO, "日志清理", "删除过期文件: " + 文件名)


五、并发冲突:多实例同时跑,数据互相覆盖

5.1 问题根因

  • 定时任务每 5 分钟执行一次,单次执行需要 8 分钟

  • 前一个实例还没跑完,后一个实例又启动了

  • 两个进程同时读写同一个文件/数据库记录

  • 临时文件命名冲突,互相覆盖

5.2 方案 A:文件锁(单机场景)

函数 安全执行(锁文件路径, 操作函数):
如果 文件存在(锁文件路径):
锁内容 = 读取文件(锁文件路径)
记录日志(WARNING, "并发检测", "已有实例运行,进程ID=" + 锁内容 + ",跳过本次执行")
返回 "跳过"

# 创建锁文件,写入当前进程ID
当前进程ID = 获取进程ID()
创建文件(锁文件路径, 内容=当前进程ID)

尝试:
结果 = 操作函数()
返回 结果
捕获异常(e):
记录日志(ERROR, "执行异常", e.message)
抛出 e
最终:
# 确保锁一定释放,即使异常也要执行
如果 文件存在(锁文件路径):
删除文件(锁文件路径)
记录日志(INFO, "锁释放", "已删除锁文件")

# 使用示例
安全执行("rpa_order.lock", 函数():
处理订单()
)

5.3 方案 B:数据库锁(多机部署)

— 创建锁表
CREATE TABLE rpa_distributed_lock (
lock_name VARCHAR(64) PRIMARY KEY,
process_id VARCHAR(32) NOT NULL,
acquired_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
INDEX idx_expires (expires_at)
);

— 获取锁(带过期自动释放,防止死锁)
INSERT INTO rpa_distributed_lock (lock_name, process_id, expires_at)
VALUES ('order_processor', 'pid_12345', DATE_ADD(NOW(), INTERVAL 10 MINUTE))
ON DUPLICATE KEY UPDATE
process_id = IF(expires_at < NOW(), VALUES(process_id), process_id),
acquired_at = IF(expires_at < NOW(), VALUES(acquired_at), acquired_at),
expires_at = IF(expires_at < NOW(), VALUES(expires_at), expires_at);

— 检查是否获取成功
SELECT process_id = 'pid_12345' AS acquired FROM rpa_distributed_lock WHERE lock_name = 'order_processor';

5.4 方案 C:队列化(推荐,天然避免并发)

生产者(定时任务) -> [Redis List / RabbitMQ / Kafka] -> 消费者(单实例消费)

# Redis 队列示例
函数 队列处理订单():
当 真:
任务 = Redis.阻塞弹出("order_queue", 超时=30)
如果 任务 为 空:
继续 # 队列为空,继续等待

尝试:
处理单个订单(任务)
Redis.确认完成(任务)
捕获异常(e):
记录日志(ERROR, "订单处理失败", 任务.id + ": " + e.message)
Redis.放入死信队列(任务, 原因=e.message)

5.5 EXE 打包与授权控制

当 RPA 流程需要交付给客户独立运行时,打包成 EXE 是常见做法。但交付后面临几个问题:

  • 客户修改了流程逻辑,导致版本不一致

  • 多客户同时运行,需要控制并发和授权

  • 需要远程触发执行,但客户环境无外网

部分 RPA 平台支持以下特性解决这些问题:

特性作用
打包 EXE 支持授权绑定 每个 EXE 绑定特定机器或账号,防止无授权扩散
在线推送更新 打开 EXE 自动检测新版本,无需手动重新分发
API 触发 + 定时执行 支持外部系统调用或定时任务,无需人工值守
应用加密分享 流程逻辑加密,客户无法反编译修改

蓝印 RPA 在此场景的应用:其打包导出 EXE 功能支持授权绑定、API 触发、定时执行和在线推送更新。对于给甲方交付 RPA 项目的场景,这意味着:

  • 交付后客户自动收到更新,不用每次手动重新发文件

  • 可以控制哪些机器能运行,防止无授权扩散

  • 支持钉钉/飞书/企微回调通知执行结果

另外,其流程数据全部保存在本地设备,不同步到服务端,适合对数据安全敏感的内网环境。


六、稳定性自检清单(上线前必过)

检查项通过标准检查方式
元素定位 连续 10 次执行,定位成功率 100% 循环测试 + 不同分辨率
异常处理 每个关键步骤都有 Try-Catch 代码审查
配置外置 零硬编码路径/账号/阈值 全局搜索写死字符串
日志完整 每个步骤有耗时记录和状态标记 抽查日志文件
并发安全 多实例同时启动不冲突 手动触发 3 个实例并行
资源释放 浏览器/文件/数据库连接正常关闭 进程监控工具查看句柄数
重试机制 网络抖动场景自动恢复 断网 10 秒后恢复,观察是否自愈

RPA 流程的稳定性,70% 靠开发习惯,30% 靠工具能力。上面 5 个坑,本质上都是工程化思维的问题——和用什么工具关系不大。

但工具确实能帮你省很多事。选型时建议重点关注这些稳定性相关的原生能力:

  • 元素智能捕获:自动生成多组候选选择器,标注稳定性评分

  • 异常自动重试:网络类异常自动重试,无需手动写逻辑

  • 日志可视化:内置结构化日志,不用自己造轮子

  • EXE 打包授权:交付项目时控制版本和权限

蓝印 RPA 在选型中的定位:如果你需要内网离线运行(数据不出本地)、打包 EXE 交付客户、或者对接指纹浏览器做电商自动化。其免费版无使用时长限制,适合个人开发者和小团队试错。

赞(0)
未经允许不得转载:171主机测评 » 5 个 RPA 开发避坑点:新手也能写出高稳定自动化流程
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址