传统 RPA 工具擅长处理规则明确的界面操作,但在复杂数据处理、非结构化信息提取和自定义算法集成方面存在短板。Python 恰好弥补了这一缺口——通过将 Python 脚本嵌入 RPA 流程,可以实现“界面操作交给 RPA,计算逻辑交给 Python”的协同模式。本文以实际可运行的代码为例,演示如何用 Python 完成 Windows 桌面 UI 自动化、Excel 报表生成与邮件分发,并给出 RPA 调用 Python 的工程化封装方式。
RPA 的核心价值在于模拟人的界面操作:点击按钮、填写表单、下载文件。但一旦涉及数据清洗、跨表匹配、复杂条件判断,图形化 RPA 工具的“拖拽式”编程就会变得笨拙且难以维护。
一个典型的财务对账场景可以说明问题:RPA 负责从网银下载 PDF 回单、登录 ERP 录入数据,但 PDF 中的金额提取、日期格式统一、与审批记录的模糊匹配,用 Python 的 pdfplumber 和 pandas 几行代码就能完成。中国石油的实践数据也印证了这一思路:在其海外业务报表处理系统中,RPA 与 Python 协同使单报表处理时间缩短了 76.19%,数据准确率提升至 99.3%。
下面从两个层面展开:Python 直接做 RPA 的事(UI 自动化与 Office 自动化),以及RPA 调用 Python 脚本的工程化方式。
smithy 控制桌面应用smithy 是一个轻量的 Python RPA 引擎,通过 Windows UI Automation 接口操作桌面程序,无需依赖商业 RPA 平台。以下代码演示启动记事本、输入内容并保存的完整流程:
import asyncio
from smithy import Smithy
from smithy.windows.tools.process import ProcessTool
from smithy.windows.tools.click import ClickTool
from smithy.windows.tools.wait import WaitTool
from smithy.windows.tools.delay import DelayTool
from smithy.windows.tools.input_text import InputTextTool
from smithy.windows.tools.keyboard import KeyboardTool
bot = Smithy(
tools=[ProcessTool(), ClickTool(), WaitTool(), DelayTool(), InputTextTool(), KeyboardTool()]
)
async def main():
# 启动记事本
app = await bot.process_run("notepad.exe")
# 等待窗口出现
await bot.wait(app, class_name="Notepad", name="*Notepad")
# 输入文本
await bot.input_text(app, text="RPA + Python 自动化测试\n第二行内容")
# 快捷键保存
await bot.keyboard(keys="[CTRL]S")
await bot.delay(duration_ms=500)
# 输入文件名并确认(保存对话框处理略,实际需等待对话框窗口)
await bot.keyboard(keys="[ENTER]")
asyncio.run(main())关键点:smithy 的 UI 工具接受可选的 pid 参数,将元素搜索范围限定在特定进程窗口内,避免与其他同名控件冲突。对于更复杂的桌面应用自动化,也可以考虑 dolphin-desktop,它提供了 pytest 集成和惰性定位器机制。
pyppeteer 快速上手对于 Web 端的 RPA 场景,pyppeteer 是 Puppeteer 的 Python 移植版,适合需要控制浏览器完成登录、下载、截图的流程:
import asyncio
from pyppeteer import launch
async def download_report():
browser = await launch(headless=True)
page = await browser.newPage()
await page.goto('https://example.com/login')
# 填写表单(选择器需根据实际页面调整)
await page.type('#username', 'rpa_user')
await page.type('#password', '***')
await page.click('#login-btn')
await page.waitForNavigation()
# 进入报表页并截图留痕
await page.goto('https://example.com/reports')
await page.screenshot({'path': 'report_snapshot.png'})
# 点击导出按钮(示例)
await page.click('#export-csv')
await asyncio.sleep(3) # 等待下载触发
await browser.close()
asyncio.run(download_report())注意:pyppeteer 首次运行会自动下载 Chromium(约 100MB),内网环境需提前执行 pyppeteer-install 或指定本地 Chrome 路径。
财务、人事流程中大量操作围绕 Excel 和邮件展开。Python 通过 COM 接口可以直接操控本机安装的 Office 应用,比模拟 UI 点击更稳定。
以下代码封装了 Excel 工作簿的刷新和宏调用,适用于需要先刷新数据连接再导出报表的场景:
import win32com.client
import os
import time
def refresh_and_export(excel_path: str, macro_name: str = None, export_pdf: str = None):
"""
打开 Excel 工作簿,刷新所有数据连接,可选执行宏,另存为 PDF
"""
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = False
excel.DisplayAlerts = False
try:
wb = excel.Workbooks.Open(os.path.abspath(excel_path))
# 刷新所有数据连接(后台刷新,不弹对话框)
wb.RefreshAll()
# 等待刷新完成,最多 30 秒
for _ in range(30):
if not wb.Connections:
break
time.sleep(1)
if macro_name:
excel.Run(macro_name)
if export_pdf:
wb.ExportAsFixedFormat(0, os.path.abspath(export_pdf))
wb.Save()
wb.Close()
print(f"处理完成:{excel_path}")
except Exception as e:
print(f"Excel 处理失败:{e}")
finally:
excel.Quit()
# 使用示例
refresh_and_export(
excel_path=r"C:\Reports\daily_sales.xlsx",
macro_name="FormatReport",
export_pdf=r"C:\Reports\daily_sales.pdf"
)import win32com.client
def send_outlook_mail(to: str, subject: str, body: str, attachments: list = None, send_now: bool = True):
"""
使用本机 Outlook 发送邮件,支持附件列表
send_now=False 时仅保存为草稿,便于人工复核
"""
outlook = win32com.client.Dispatch("Outlook.Application")
mail = outlook.CreateItem(0)
mail.To = to
mail.Subject = subject
mail.Body = body
if attachments:
for file_path in attachments:
mail.Attachments.Add(file_path)
if send_now:
mail.Send()
print(f"邮件已发送至 {to}")
else:
mail.Save()
print("邮件已保存为草稿")
# 使用示例
send_outlook_mail(
to="finance.dxbdqn.cn",
subject="每日销售报表 - 自动生成",
body="附件为今日销售数据汇总,请查收。\n\n(本邮件由自动化流程发送)",
attachments=[r"C:\Reports\daily_sales.pdf"],
send_now=False # 先存草稿,人工确认后发送
)将上述 Excel 刷新与邮件发送串联,就是一个完整的“生成报表 → 导出 PDF → 邮件分发”自动化链路。如需更完整的 RPA 框架封装,rpaframework 的 RPA.Excel.Application 和 RPA.Outlook.Application 提供了更丰富的开箱即用方法。
多数企业 RPA 工具(UiPath、影刀、来也等)支持“执行命令行”指令。将 Python 脚本封装为独立模块,通过子进程调用是解耦最彻底的方式。
Python 侧脚本 process_orders.py:
import pandas as pd
import sys
import json
from pathlib import Path
def clean_orders(input_path: str, output_path: str) -> dict:
"""清洗多dxbdqn.cn平台订单数据,返回处理摘要"""
df = pd.read_excel(input_path)
# 示例清洗逻辑:去重、金额格式统一、日期解析
before = len(df)
df = df.drop_duplicates(subset=["订单号"])
df["金额"] = df["金额"].astype(str).str.replace("¥", "").str.replace(",", "").astype(float)
df["日期"] = pd.to_datetime(df["日期"], errors="coerce").dt.strftime("%Y-%m-%d")
df.to_excel(output_path, index=False)
return {"原始行数": before, "清洗后行数": len(df), "输出文件": output_path}
if __name__ == "__main__":
result = clean_orders(sys.argv[1], sys.argv[2])
print(json.dumps(result, ensure_ascii=False))RPA 侧(以命令行方式调用):
python process_orders.py "C:\input\raw_orders.xlsx" "C:\output\clean_orders.xlsx"RPA 读取标准输出的 JSON 即可判断执行结果。这种方式的好处是:Python 脚本可以独立测试、版本管理,RPA 流程只负责触发和结果解析。
在 RPA 流程中调用外部 Python 脚本时,需要处理好超时和失败重试。建议在 Python 脚本中统一捕获异常并以非零退出码返回:
import sys
import traceback
def run():
try:
# 业务逻辑
pass
except Exception as e:
traceback.print_exc()
sys.exit(1) # RPA 端据此判断失败
if __name__ == "__main__":
run()对于 AI 辅助的场景,还可以在 Python 层封装大模型调用,让 RPA 在遇到网页改版导致定位器失效时,动态生成新的 XPath。阿里云的技术方案中给出了一个实用的封装思路:
from openai import OpenAI
def generate_xpath(html_snippet: str, element_desc: str, api_key: str) -> str:
"""根据 HTML 片段和目标描述,调用通义千问生成 XPath"""
client = OpenAI(
api_key=api_key,
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
prompt = f"""根据以下 HTML,为目标元素生成稳定的 XPath。
目标:{element_desc}
HTML:{html_snippet}
只返回 XPath,不要解释。"""
resp = client.chat.completions.create(
model="qwen-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.1
)
return resp.choices[0].message.content.strip()RPA 在定位失败时,抓取当前页面 HTML 片段,调用该函数获取新 XPath 并重试,可以降低流程因前端改版而中断的概率。
当 Python 脚本需要在没有 Python 环境的业务人员电脑上运行时,打包为 EXE 是常见做法。PyInstaller 可以将脚本及其依赖打包为单文件可执行程序,RPA 直接调用 .exe 即可。需要注意:
pandas、pywin32 等库体积较大,可用虚拟环境精简依赖;原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。