1. 内容整体设计与思路拆解
1.1 表单自动化到底在解决什么问题
先直接给结论:程序自动化填写网页表单数据,就是把人类在浏览器里“输入框打字、点按钮、选下拉框、上传文件、提交数据”这一整套重复动作,交给程序去执行。听着很简单,但实际落地时你会发现,它真正解决的不只是“打字”这个动作,而是三个更深层的痛点:批量处理、准确性保障和跨系统数据流转。
举个最典型的场景。我在做企业内部的数据管理系统对接时,遇上过一个特别头疼的需求:每天早晨要把上游ERP系统导出的销售订单数据,逐条录入到另一个第三方SaaS平台的网页后台。那个SaaS平台没有开放API,只能用网页表单手工录入。人工录入100条订单,按每条2分钟算,就是3个多小时,中间还不能分心,一不留神就录错数字。用程序自动化来做,100条订单大约5分钟跑完,数据准确率接近100%,而且录完还能自动截图留证。这省下来的不光是时间,更是让业务部门的人从枯燥的重复劳动里解放出来。
这个项目非常适合三类人来参考:一是公司内部做运营、客服、人事这类工作、天天跟多个网页后台打交道的业务人员;二是被各种系统间数据互通难题折磨的IT运维或开发人员;三是对爬虫、自动化测试、RPA感兴趣,想入门试试自己写一个好玩工具的技术爱好者。
1.2 核心方案选型:为什么我最终选择了Python + Playwright
市面上做网页表单自动化的方案并不少,我大致把它们分成四个流派:
| 方案流派 | 代表工具 | 优势 | 劣势 |
|---|---|---|---|
| 浏览器扩展型 | iMacros、油猴脚本 | 上手极快,浏览器内直接录放 | 跨浏览器兼容差,逻辑能力弱 |
| 商业RPA工具 | 影刀、UiBot、按键精灵 | 有图形化流程编排,业务人员友好 | 成本高,运行依赖Windows环境,调试黑盒 |
| 老牌自动化框架 | Selenium | 生态成熟,资料多,支持几乎所有浏览器 | 安装配置偏重,执行速度慢,API设计老旧 |
| 新一代自动化框架 | Playwright | 安装简单,API现代化,自动等待,执行快 | 相对年轻,部分冷门浏览器支持不及时 |
我这次项目的核心需求是“批量、稳定、可重复执行”,同时希望代码尽量简洁、维护成本低,所以最终敲定了Python + Playwright的组合。国内很多自动化测试文章还在推Selenium,但Playwright在几个关键点上体验完全是跨时代的:它自带自动等待机制,元素还没加载出来时会主动等待,而不像Selenium那样经常抛NoSuchElementException逼你到处写sleep;它支持多浏览器内核,一套代码既能在Chromium跑,也能切到Firefox或WebKit;它还能自动跟踪页面的网络请求和响应,排查问题极其方便。
当然也不是说Selenium被淘汰了,如果团队里全是老手、已有大量基于Selenium的框架沉淀,那继续用它完全合理。但如果你是新起一个表单自动化的项目,我的建议很明确:直接从Playwright开始,它能让你少走至少两个月的弯路。
1.3 明确边界:哪些表单适合自动化,哪些不适合
碰过自动化的人可能会有一种错觉,觉得网页里所有的表单都能用程序自动填。实际上,表单自动化的可行性有非常清晰的边界。我总结出下面几条“铁律”:
- 适合自动化的表单:有明确的输入框、下拉框、单选框结构;元素有稳定的id、name属性或可读的CSS路径;页面加载后表单结构不频繁变化;数据来源是结构化的(Excel、数据库、CSV或上游接口返回的JSON)。
- 不适合自动化的表单:需要短信验证码、滑动拼图验证码的人工验证环节;加密性极强的网银类页面,或者用了极其复杂的前端Actionscript渲染(现在很少了);页面更新频繁且没有任何稳定标识的表单。
这里特别想聊一下验证码。现在很多网站都挂了行为验证码,比如滑块拼图、点选文字。如果你本身在用这个网站,也有正常的使用权限,只是想把重复的录入工作自动化,那可以考虑接入打码平台来解决验证码识别。但在做之前务必确认这样操作是否违反了网站的用户协议,我自己在项目里都会优先跟对方确认授权,能走API就走API,不能走API就控制执行频率,避免对目标网站造成压力。合规永远是第一位的,这一点往下渗透到所有实操环节里都非常重要。
2. 核心细节解析与实操要点
2.1 元素定位:表单自动化的地基
无论你用Selenium还是Playwright,表单自动化的第一步永远是“找到元素”。这是整个自动化链路里最容易出错、也最考验功力的环节。如果把自动化工程比作建房子,元素定位就是地基,地基不稳,后续所有脚本都随时可能塌。
Playwright里最常用的定位方法有三个:locator配合CSS选择器、get_by_*系列方法、以及XPath。我个人的习惯是优先用locator+ CSS选择器,因为它性能好、语法简洁、可读性强。举例来说,一个登录表单的账号输入框、密码输入框和登录按钮,用CSS定位器可以这样写:
from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto('https://example.com/login') page.locator('#username').fill('admin') page.locator('input[type="password"]').fill('pass123') page.locator('button:has-text("登 录")').click() browser.close()这段代码能跑通的前提是页面元素的id和属性稳定。但实际项目里很多前端框架(尤其是Vue、React重构过的系统)会生成一堆随机id,比如input_8u4f9a2k1z,这种id每次刷新都会变,直接写进脚本里就是给自己埋雷。这种情况下,我的思路是改用“语义化定位”:按钮就找按钮里的文字,输入框就找它前面的label文字,又或者是用page.get_by_role()来按角色定位,这也是Playwright非常推荐的做法。
# 更健壮的定位方式:优先使用角色和文本 page.get_by_label('用户名').fill('admin') page.get_by_role('button', name='登录').click()get_by_role这个方法在国内技术文章里提的不多,但它其实特别强大。它会根据元素的无障碍角色(按钮、输入框、链接、复选框等)以及可访问名称来定位元素,模拟真实用户“看到”页面的方式,当你用这种方式定位时,脚本对前端实现的依赖度会低很多。不过有一个前提:前端工程师写代码时得注意加aria-label等无障碍属性,否则这个方法也找不到目标。
2.2 等待策略:不要再用time.sleep绑定时炸弹
新手写表单自动化最容易犯的一个错误,就是动不动time.sleep(5),让程序干等着。我见过一个同事写的脚本,整个流程里十几个sleep,最长的居然等了30秒。这样做的后果是:网络慢了页面没加载完,sleep时间不够就直接报错;网络快了页面早就好了,还得白白等好几秒,效率极其低下。这完全是用“程序员思维”解决“页面时序问题”,越搞越僵硬。
Playwright在这个问题上给出了非常漂亮的答案:所有定位器操作默认都会自动等待元素达到可操作状态。什么意思?就是说当你调用fill()时,框架会先等元素出现在DOM里、可见、可编辑,才会开始输入。这一套机制是内置的,而不是靠你写time.sleep去“赌”页面加载速度。
如果你确实有特殊场景需要显式等待某个条件成立,Playwright也给了对应的API,常见的我列在这里:
- 等待元素附加到DOM并可见:
page.locator('selector').wait_for(state='visible') - 等待网络请求完成:
page.expect_response('**/api/save')配合点击操作 - 等待元素消失:
page.locator('selector').wait_for(state='detached') - 等待URL地址变化:
page.wait_for_url('**/success')
这个设计哲学值得展开说几句。Playwright的“自动等待”背后是一套严密的状态机,框架在执行每个动作前会轮询检查元素的“动作就绪状态”,比如可点击性要求元素是可见的、稳定的、接收事件不被遮挡。这种机制的最终效果,就是让代码变得极其“优雅”:你不需要关心网络抖动、资源加载慢这些乱七八糟的因素,脚本会在正确的时机执行正确的操作。写出来的代码既好读,又不像传统Selenium脚本那样布满sleep时间线,看着就想重构。
2.3 表单中各类控件的填写方式
表单绝不是只有“输入框”和“按钮”这两个元素。真实业务里更多的是下拉框、单选按钮、复选框、文件上传、日期选择器等“花式控件”,每一种的自动化方式都有一点差异。
先讲下拉框。原生HTML的<select>元素,Playwright里直接提供了一个非常语义化的API叫select_option,你在下拉框的定位器上直接调用,传value、label或者index都可以。但要注意,现在很多后台系统用的是自定义下拉组件(比如Element UI的el-select),并不是原生<select>,这时候就得先点击下拉框,等选项弹出来,再点击对应的选项文本。
# 原生select page.select_option('select#province', label='广东省') # 自定义下拉(例如Element UI) page.locator('.el-form-item:has-text("省份") .el-select').click() page.locator('.el-select-dropdown__item:has-text("广东省")').click()再讲复选框和单选框。这两种控件如果用原生HTML实现,直接调用.check()/.uncheck()以及.check()即可,Playwright会处理内部交互的顺序。如果是自定义组件,比如Switch开关、按钮形式的单选,本质上还是模拟点击。这里我建议一个调试方法:在浏览器开发者工具里用元素选择器确认组件渲染出来的真实HTML结构,你光看React或Vue的组件代码是猜不到最终DOM长什么样的。
文件上传是很多自动化的“老大难”。玩过Selenium的人应该都被input[type=file]的隐藏输入框坑过,元素明明在DOM里但不可见不可点。Playwright的做法比较直接:文件上传控件哪怕隐藏了,你也能直接给set_input_files()传本地文件路径,框架会绕过可见性判断直接设置文件队列。
page.locator('input[type="file"]').set_input_files('./data/order_list.xlsx')2.4 数据来源与数据清洗:自动化前必须做好的功课
表单自动化的输入端是数据,数据质量决定了整个自动化的成败。之前我提过,数据一般来自Excel、CSV、数据库或者API接口。但这里有个隐藏的坑:原始数据很难直接“灌”进网页表单。
比如我从Excel里读出来的日期可能是2024/1/5这种格式,但网页表单要求的格式是2024-01-05;再比如Excel里的手机号列如果格式没设置好,读出来会变成1.38E+10这种科学计数法,直接填进网页里就是灾难。更常见的还有数据里包含前后空格、全角半角符号混用、空值等等。
所以我在项目里都会加一道“数据清洗”的工序,清洗规则一般包含:
- 字段格式统一(日期、金额、百分比格式化为目标表单要求的格式)
- 字符集规范化(全角转半角、统一引号、去多余空格)
- 必填项缺失校验(缺了就别填这条,记日志后面人工处理)
- 重复数据标记(根据业务主键去重,避免重复提交)
数据清洗可以用pandas来处理,几百上千行数据对它来说小菜一碟。这里给个简单示例:
import pandas as pd df = pd.read_excel('./data/orders.xlsx') df['phone'] = df['phone'].astype(str).str.replace(r'\.0$', '', regex=True) df['date'] = pd.to_datetime(df['date']).dt.strftime('%Y-%m-%d') df['remark'] = df['remark'].fillna('').str.strip()2.5 文件下载与截图留证
自动化录入数据这件事,最后一定要有一个“证据链”,否则出了问题扯皮都说不清楚。我的习惯是每录完一条数据、成功提交后,自动截一张全页面截图,或者把提交结果页面的关键信息抓取下来写到日志里。
Playwright的截图实现极其简单,就一行代码:
page.screenshot(path=f'./evidence/order_{order_id}.png', full_page=True)full_page=True参数表示截全页面长图,这在记录表单提交结果时特别有用,能把整个回执信息截下来。如果表单提交后是弹窗提示,截图前先等一下弹窗出现;如果提交后跳到列表页,就等新页面加载完再截图。截图文件命名时把这条数据的业务主键塞进去,后面追踪线索方便得多。
有些场景下还得处理文件下载,比如系统支持把“待填数据”导出成Excel。Playwright里用page.expect_download()来捕获下载事件,下载的文件默认放在临时目录,需要主动调用save_as()保存到指定位置。
with page.expect_download() as download_info: page.locator('button:has-text("导出模板")').click() download = download_info.value download.save_as('./data/template.xlsx')3. 实操过程与核心环节实现
3.1 环境准备:从零到能跑通第一条脚本命令
动手写代码之前,先把运行环境搭起来。这一步看起来琐碎,但很多人的自动化项目就死在环境上——尤其是Windows下,Python版本混乱、环境变量没配好、浏览器驱动不匹配,各种问题能让你还没开始写业务代码就先劝退。
我的建议是用Python 3.10以上版本,避免老版本在新语法上的一些兼容性尴尬。创建虚拟环境是一个非常好的习惯,不会让全局Python环境被各种依赖污染。具体步骤如下:
# 创建项目目录和虚拟环境 mkdir form_automation cd form_automation python -m venv venv # Windows激活虚拟环境 venv\Scripts\activate # macOS/Linux激活虚拟环境 source venv/bin/activate # 安装Playwright pip install playwright # 安装所需的浏览器内核(默认安装Chromium) playwright install chromium有个小细节值得提醒:默认运行playwright install会同时下载Chromium、Firefox和WebKit三个内核,体积不小。如果你确定只跑Chromium,可以指定只装一个,省时省空间。
完成这一步后,可以先写一个“访问百度首页并打印标题”的最小脚本,验证整套链路是否通顺。如果这一步卡住了,VNC、无头模式、系统依赖等都是坑,别急着往后写代码。
3.2 用录制工具快速“生成”表单操作的原始脚本
不管你是第一次接触Playwright,还是写过不少自动化测试的老手,我都建议你在开工时先用Playwright的codegen录制功能“打底”,它能让你在浏览器里像正常用户一样操作几步,然后自动生成对等操作的Python代码。这个功能对表单自动化特别有用,因为很多页面的元素结构你并不清楚,录制过程中生成的代码直接告诉你点击了哪个按钮、填写了哪个输入框,定位器直接可用。
用法非常简单:
playwright codegen https://example.com/form执行后浏览器窗口会打开目标页面,同时旁边打开一个Playwright Inspector窗口。你在浏览器里做的每一步操作,比如点击输入框、输入文字、选下拉选项、点提交按钮,Inspector窗口里都会实时生成对应的Python代码。操作结束后,把生成的代码复制到一个.py文件里保存。
需要说明的是,录制生成的代码只是一个起点,生产环境里你不能指望它一步到位。它生成的定位器有时候非常长,依赖一堆中间节点的class,维护性很差。我的习惯是拿录制结果当“路线图”:先看清楚页面元素大致长什么样,提交流程是几步,然后亲手把定位器改写成更稳定、更简洁的写法。但如果你是第一次接触某个后台系统、连表单有什么字段都不知道,录制能让你在5分钟内摸清页面结构,这个效率是手写代码没法比的。
3.3 完整案例:批量提交100条数据到后台管理系统
有了前面这些基础,现在拼装一个接近真实业务的完整示例。假设我手上有一份员工花名册Excel,需要导入到一个内部HR管理系统的网页表单中,每条记录包含姓名、工号、部门、入职日期、手机号、邮箱六个字段,表单里还有“性别”单选和“常驻城市”下拉框,提交后系统会跳到一个“添加成功”的提示页。
先写好数据读取与清洗的模块:
import pandas as pd from playwright.sync_api import sync_playwright df = pd.read_excel('./data/employees.xlsx') df = df.fillna('') df['phone'] = df['phone'].astype(str).str.replace(r'\.0$', '', regex=True) records = df.to_dict('records') print(f'共读取 {len(records)} 条待录入记录')然后核心的提交函数:
def submit_employee(page, record): page.goto('http://hr-system.local/employee/add') # 填写文本输入框 page.get_by_label('姓名').fill(record['name']) page.get_by_label('工号').fill(record['employee_id']) page.get_by_label('入职日期').fill(record['hire_date']) page.get_by_label('手机号').fill(record['phone']) page.get_by_label('邮箱').fill(record['email']) # 处理单选框:按值选择 page.locator(f'input[name="gender"][value="{record["gender"]}"]').check() # 处理自定义下拉框 page.locator('.city-select').click() page.locator(f'.city-option:has-text("{record["city"]}")').click() # 点击提交 page.get_by_role('button', name='提交').click() # 等待成功提示页出现 page.wait_for_url('**/success', timeout=10000) page.screenshot(path=f'./evidence/{record["employee_id"]}.png', full_page=True)主体循环里加上异常处理和重试逻辑:
def main(): fail_list = [] with sync_playwright() as p: browser = p.chromium.launch(headless=True) context = browser.new_context() page = context.new_page() for idx, record in enumerate(records, 1): try: submit_employee(page, record) print(f'[{idx}/{len(records)}] 工号 {record["employee_id"]} 提交成功') except Exception as e: print(f'[{idx}/{len(records)}] 工号 {record["employee_id"]} 提交失败: {e}') fail_list.append(record['employee_id']) browser.close() if fail_list: print(f'\n共有 {len(fail_list)} 条失败记录: {fail_list}') else: print('\n全部提交成功') if __name__ == '__main__': main()这段代码有几个值得留意的细节。第一,headless=True表示无头模式,也就是不弹出浏览器界面,适合服务器上运行。但前期调试时我建议先headless=False,亲眼看它每一步操作是否正确,等稳定了再转无头模式。第二,成功页判断我用的是wait_for_url('**/success'),而不是盲目sleep,这是最稳的等待方式。第三,失败记录不会让整个程序崩溃,而是收集起来最后集中处理,这才是面向真实业务的容错设计。
3.4 参数计算与运行策略:频率控制和数据分批
表单自动化本质上是在“模拟真人操作”,所以运行节奏也需要有讲究。如果你脚本里几百条数据像机关枪一样啪啪啪地连续提交,任何正常网站的安全策略都会把你拦下来。我在实际项目里的经验是:“快”不是目标,“稳”才是。
我通常会做一个很简单的频率控制——每提交一条数据后随机停顿几秒钟。停顿时间不要固定写死成3秒,而是用random生成一个介于2到5秒之间的随机值,这样更接近人类操作节奏,对目标服务器的压力也更友好。
import random import time # 在每次提交之间加入随机延时 time.sleep(random.uniform(2, 5))如果数据量特别大,比如一次性几万条,我还会额外做一个多账号轮换或者多批次拆分的方案。但这已经属于比较重的工程了,在一般的企业内部业务场景里,控制好频率就足够了。核心原则是:我们的目标是完成自己的正常工作任务,不是给别人的服务器制造压力,更不是把自己玩进风控名单。
3.5 数据一致性校验:自动化之后如何确保数据正确
自动化把数据填进表单里,并不代表数据就一定正确。我遇到过这样一个事故:脚本跑了两个小时,日志显示100条数据全部提交成功,结果第二天业务部门反馈有6条数据在系统里查不到。排查下来,原因是这6条记录提交时短信验证码发送失败,页面弹出了“保存失败”的toast,但我的脚本还在机械地执行“等待成功页URL”的逻辑,最终以为成功了。
这给我狠狠上了一课:表单自动化的最后一步,必须是“结果校验”。校验方案有两个层次:基础方案是提交后抓取页面上出现的提示文案,判断是不是“添加成功”;进阶方案是通过目标系统的查询接口或列表页搜索提交的数据主键,确认数据真的落库了。
# 基础校验:检查toast提示 page.wait_for_selector('.el-message--success') toast_text = page.locator('.el-message--success').inner_text() assert '成功' in toast_text, f'提交后提示异常: {toast_text}'一定要把校验逻辑嵌入到主流程里,任何一步校验不过就立即标记失败并截图,而不是让它“蒙混过关”。这看起来是多写了几行代码,但能避免大量后续人工核对的时间。
4. 常见问题与排查技巧实录
4.1 元素定位不到,脚本频繁崩溃怎么办
这是表单自动化里最高频的问题,没有之一。我总结了几种典型情况和对应解法:
| 现象 | 常见原因 | 解决方案 |
|---|---|---|
TimeoutError等待定位器超时 | 元素确实不存在于当前页面,或还在异步加载 | 核对选择器拼写;用page.wait_for_selector给足加载时间;确认页面是否发生了跳转 |
| 元素能找到但点击无效 | 元素被遮罩、被fixed定位覆盖 | 用force=True强制点击前先排查遮罩;滚动到元素可见区域 |
| 同一页面有多个相同class的元素 | 定位器匹配了多个节点,框架不知道选哪个 | 用:nth-match()或filter()精确到目标索引;改用语义化的get_by_role |
| 定位器在本地调试OK,上线后失效 | 前端频繁发版导致DOM结构变化 | 前端加># 保存登录态 context.storage_state(path='./state.json') # 加载登录态 context = browser.new_context(storage_state='./state.json')这里有个细节要留意:存储状态里包含了所有Cookie和本地存储信息,所以如果目标系统把登录态放在localStorage而不是Cookie里,也能一并恢复。保存登录态的最佳时机是完成登录后、进入首页时,这样里面会带上最完整的会话状态。 登录态过期也是常见问题。我的策略是给关键操作加一个异常判断:如果页面跳回了登录页,就抛出特定异常并触发重新登录的流程,重试不超过三次。不要让脚本像无头苍蝇一样在登录页上找不存在的输入框。 4.3 iframe内的表单怎么处理嵌入式iframe是网页表单自动化的另一大坑。如果你在做低代码平台、客服系统或者第三方支付页面,表单往往被嵌在iframe里。Playwright处理iframe的方式比Selenium的 如果页面上有多个iframe嵌套, 4.4 遇到验证码怎么办,说说合规的处理思路表单自动化一定会遇到验证码,这是无法回避的现实。从合规和工程两个角度,我的建议分三层: 第一层,正本清源。如果你的自动化目的是处理自己的业务数据、且得到系统管理方的授权,先看看能不能通过API方式完成操作。UI自动化是兜底手段,不是首选方案。 第二层,降低触发频率。验证码的触发机制通常和频率相关。合理地控制脚本运行节奏、模拟真人操作间隔、错峰执行,能显著降低验证码出现的频率。我刚做自动化时踩过这个坑,脚本半夜跑大批量任务,早上起来看日志发现卡在验证码页面上,白白浪费了一晚上。 第三层,如果确实必须处理验证码,优先考虑接入正规打码平台,或者是内部系统管理员提供万能验证码(这种情况在内部系统里很常见)。自己写OCR识别滑块的,说实话成功率不高,维护成本也不低,并不划算。 4.5 跨平台运行与任务定时调度本地开发调试通过后,这类脚本通常要放到服务器上长期运行。跨平台时有几个易被忽视的问题:第一是浏览器内核路径,Windows和Linux下Chromium安装路径不一样,建议让Playwright自己管理内核,而不是手动指定系统Chrome路径;第二是文件路径分隔符,读写Excel或保存截图时,用 如果你打算让脚本定时执行,自己写while True循环非常不推荐。Linux下用crontab,Windows下用系统任务计划程序,就可以把脚本挂在操作系统上定时触发。我的标准做法是:脚本配置项全部放在外部config文件里,日志输出到固定目录,执行结果发到企业微信或钉钉机器人,这样全流程就基本闭环了。倒是有一点得提醒:定时任务执行时环境变量可能没有你终端里的那么全,脚本里尽量少依赖环境变量,各种配置直接写在相对路径下。 5. 扩展思考与应用场景延伸5.1 从表单自动化到RPA:一整套流程自动化的思维框架写到这里,你会发现程序自动化填写网页表单只是“流程自动化”的一个缩影。如果后台系统没有API,这就是连接两个系统的桥梁;如果有API,自动化脚本就可以退居二线做巡检和兜底。这套“数据读取 → 数据清洗 → UI操作 → 结果校验 → 异常告警 → 留痕归档”的方法论,放之任何重复性工作场景都能直接用。 比如客服每天要把订单信息录入ERP系统、人事要批量维护员工资料、财务要在税务网站上做申报,背后都是同一个套路。用自动化把这些流程从人肉点击中解放出来,无论从效率还是准确率来说都是肉眼可见的提升。这也是为什么现在RPA、流程自动化相关岗位需求量那么大,因为企业里的“系统孤岛”问题永远不会消失,而API对接又没那么快完成,UI自动化作为最后一百米的连接器,价值始终存在。 5.2 和主流CI/CD流水线的结合如果你所在团队有自动化测试的沉淀,这套表单自动化脚本完全可以纳入到GitLab CI/CD或Jenkins流水线里,作为一个定时执行的轮询任务。比如每天凌晨从数据库读取前一天的订单数据,自动提交到外部监管系统,然后把执行结果以测试报告的形式输出。 我在一个项目中就干过这种事:把提交脚本打包成Docker镜像,在GitLab的Schedule Pipeline里定时触发,执行完将日志和截图统一收集到MinIO对象存储。这样整个流程完全无人值守,出了问题还可以通过Pipeline记录追踪到具体是哪一批数据执行失败。这是一个很好的工程化方向,但这篇文章就不再展开了。 5.3 最后的一点个人建议做这种自动化项目,最大的坑不在技术,而在于“需求边界”。接需求时先问清楚:这个系统有没有官方API?数据源是哪里?执行频率多高?出了问题谁负责?把这些问题摆在台面上,远比写几行代码重要。因为技术方案的选型、代码架构的设计,全是围绕这些业务问题展开的。 我在实际项目中还有一个体会:表单自动化脚本的运行环境尽量用独立浏览器实例,不要在你日常办公的电脑上直接跑大批量任务。一方面是不稳定因素太多,另一方面是办公电脑休眠、锁屏、断网都会影响任务中断,不如丢到服务器或专门的虚拟机里,稳定省心。 另外就是留痕。所有关键的操作节点,能截图就截图,能写日志就写日志。做到每一步可回放、每一条数据可追溯,这在自动化出了问题时能救你一命。我见过太多人写完自动化就删掉了日志和截图逻辑,出问题时只能抓瞎。别学他们,这个习惯一定要养成。 |