云任务自动化里最容易被忽略的一类失败:静默跳过
## 引子
我在做一批云平台的日常任务自动化。跑了一周后对账,发现有个任务的积分一直没到,但脚本日志里每次都显示「成功」。
问题不是脚本报错,而是**它以为自己做成了**。
这篇记录三类「静默跳过」,以及怎么把它们变成显式失败。
## 案例一:点击坐标命中了错误元素
脚本用 CDP 发鼠标事件点按钮,日志显示点击成功,但按钮毫无反应。
**排查**:把该坐标下的元素栈 dump 出来:
```javascript
document.elementsFromPoint(1045, 84).map(e => e.tagName + '.' + e.className)
```
结果第一个是 `SPAN.status-btn__badge-wrap`——坐标命中的是最内层的**数字徽标**,而不是按钮本体。
**修复**:改用完整事件序列派发到目标元素,绕过坐标:
```javascript
const el = document.querySelector('.status-btn__text');
const rr = el.getBoundingClientRect();
const o = {bubbles: true, cancelable: true, view: window,
clientX: rr.x + rr.width/2, clientY: rr.y + rr.height/2, button: 0};
el.dispatchEvent(new PointerEvent('pointerdown', o));
el.dispatchEvent(new MouseEvent('mousedown', o));
el.dispatchEvent(new PointerEvent('pointerup', Object.assign({}, o, {buttons: 0})));
el.dispatchEvent(new MouseEvent('mouseup', Object.assign({}, o, {buttons: 0})));
el.dispatchEvent(new MouseEvent('click', Object.assign({}, o, {buttons: 0})));
```
**关键**:点完必须回读状态,而不是假定成功。
```python
state = eval_js("(() => { const sb = document.querySelector('.status-btn'); return sb ? /starred/i.test(sb.className) : null; })()")
assert state is True, "Star 未生效"
```
## 案例二:按钮在 Shadow DOM 里
`document.querySelector('button')` 返回 null,但截图里按钮明明在那儿。
```javascript
document.querySelectorAll('*').forEach(e => {
if (e.shadowRoot && /立即购买/.test(e.shadowRoot.textContent)) {
console.log('found in:', e.tagName); // CC-BUYLAYER
}
});
```
元素在 web component 的 shadow root 内,普通 querySelector 穿不过去。
**修复**:
```javascript
const host = document.querySelector('cc-buylayer');
const btn = [...host.shadowRoot.querySelectorAll('*')]
.find(e => e.textContent.trim() === '立即购买');
btn.click();
```
## 案例三:任务规则里藏了「每日不同」的约束
任务卡片写着「每日 Star 一个仓库」,我每天去 Star 同一个仓。
脚本每天返回成功,积分一直不到。
直到看了任务指南原文:
> 每日需 Star **不同项目**且**不可取消 Star**
两个条件都不满足——同一个仓重复 Star,第二天实际是「取消 Star」。
**这类坑的根本原因**:脚本只检查「操作发出了」,没检查「业务上算不算数」。
## 通用对策
| 层次 | 做法 |
|---|---|
| 操作层 | 用元素引用而非坐标;必要时潜入 shadowRoot |
| 状态层 | 每次操作后回读关键属性(class / aria / value)|
| 业务层 | 读任务规则原文,把约束条件编码成断言 |
最后一层最容易被跳过。但恰恰是它决定了「做完了」和「算数了」之间的差距。
## 一个检查清单
自动化跑批之前,先问自己四个问题:
1. 这个操作**成功的判据**是什么?(不是「没报错」)
2. 我能**回读**这个判据吗?
3. 业务规则里有没有**次数/去重/顺序**约束?
4. 失败时我会**知道**吗?还是静默跳过?
四个问题都答得上来,才能把这个自动化挂到定时任务上。
## 小结
失败分两种:显式失败会报错,能修;静默跳过显示成功但没生效,更危险。
把「假成功」变成「真失败」,是自动化从能跑到可托付的分界线。
- 点赞
- 收藏
- 关注作者
评论(0)