


#WorkBuddy#
用 WorkBuddy 的朋友应该都知道它的成长计划:每天打开客户端,左下角会弹一个「立即领取」的每日积分入口,领了就是 100 积分。听起来很简单,但真要坚持 30 天一天不落,其实挺反人性的——忙起来忘了点、周末没开电脑、出差用另一台机器,一个月总能漏个几天。一个月按 30 天算就是 3000 积分的保底收益,漏一天少 100,攒盒子、开奖励的速度直接被拖慢。
我的思路很简单:既然 WorkBuddy 自带「定时任务」能力,为什么不让 AI 自己在每天凌晨替我把这 100 分领了?不碰协议、不做任何破解,就是用 UI 自动化老老实实替你点一次按钮。落地之后已经稳定跑了一段时间,实测日志在文末,当天 0 点 01 分触发、0 点 02 分领取成功,全程无人值守。
下面把完整方案拆开讲,脚本可以直接抄走。
先看架构。整个方案只有两个组件:
为什么要双路径?因为每天第一次打开 WorkBuddy 时,客户端左下角会弹「立即领取」弹窗(路径 A,最省事);但如果你当天已经打开过客户端、弹窗没了,就得走兜底路径——从个人菜单进「成长计划」,在网页的成长中心里找到领取按钮点掉(路径 B)。两条路径串行尝试,命中任意一条就收工,都领不到就写日志退出,绝不误点。
设计上还有三个刻意的小细节:
RESULT=SUCCESS(今天领到了)或 RESULT=ALREADY(今天已经领过,页面没有可点的按钮),两种都算正常收工,重复跑不会出错;脚本只依赖 uiautomation 和 Pillow 两个 pip 包。核心逻辑三步:
第一步:找到 WorkBuddy 客户端窗口。 桌面顶级窗口里按窗口名精确匹配,避免抓到浏览器里同名的页面:
def get_client():
root = auto.GetRootControl()
for c in root.GetChildren():
try:
if (c.Name or '') == 'WorkBuddy' and c.ClassName == 'Chrome_WidgetWin_1':
return c
except Exception:
pass
return None第二步:路径 A——轮询等弹窗。 在 60 秒窗口里每 5 秒扫一次「立即领取」按钮,命中且可见就直接点:
def step1_popup(win, wait_sec=60):
win.SetActive()
deadline = time.time() + wait_sec
while time.time() < deadline:
for nm, ct, ctrl, r in find_buttons(win, ('立即领取',)):
if visible(r) and click_ctrl(ctrl):
return True
time.sleep(5)
return False第三步:路径 B——进成长计划网页兜底。 先点个人菜单里的「成长计划」项,等 Edge 打开成长中心页面,再在页面控件树里扫「领取/签到」类的真按钮(排除纯文本)点下去:
def step3_claim_on_web(edge):
for nm, ct, ctrl, r in find_buttons(edge, ('领取', '签到'), maxhits=30):
if ct == 'TextControl':
continue # 纯文本说明文字不是按钮,跳过
if click_ctrl(ctrl):
return True
return False # 页面上没有可点按钮 = 今天已经领过find_buttons 是一个通用的控件树遍历器:递归走 UIA 树,按名称关键词收集 Button/Hyperlink/Text 控件,同时用黑名单过滤危险词。完整脚本在文末命令块里,整段复制就能用。
WorkBuddy 左侧栏有「定时任务」入口,点「新建」:
python wb_checkin.py(脚本保存路径自己定);建好之后在任务列表里能看到它每天"运行中"的状态卡片。我的任务列表里它已经连续多天 00:01 准时运行了。
上线后我留了完整日志。最近一次运行(就是写这篇文章的当晚):
[10-16 00:01:59] === wb_checkin start ===
[10-16 00:01:59] step1: wait popup claim button (60s)
[10-16 00:02:12] popup found: 立即领取 (268,937,332,961)[64x24]
[10-16 00:02:16] claimed via popup
RESULT=SUCCESS从触发到领取成功 17 秒。前一天走的是路径 B(弹窗已被我手动打开客户端时关掉),脚本自己进成长计划页面完成检查。也就是说不管我当天用不用 AI、开不开客户端,这 100 分都稳了。
算一笔账:100 积分/天 × 30 天 = 每月 3000 积分保底,一年 36500+。以前手动领取总有遗漏,现在漏签率直接归零。这套"定时任务 + 双路径 UI 自动化"的架子是通用的,换个按钮文案就能用来做别的每日签到类自动化。
完整脚本 wb_checkin.py(先装依赖:pip install uiautomation pillow):
# -*- coding: utf-8 -*-
# WorkBuddy 每日 100 积分自动领取(双路径)
# 路径A: 客户端左下角弹窗「立即领取」;路径B: 个人菜单->成长计划->网页领取
# 退出标记: stdout 最后输出 RESULT=SUCCESS / RESULT=ALREADY / RESULT=FAIL
import sys, time, traceback
from datetime import datetime
import uiautomation as auto
LOG = 'wb_checkin.log' # 日志落在脚本同目录
BAD_KWS = ('购买', '升级', '套餐', '退回', '兑换积分', '立即体验', '加购')
GOOD_KWS = ('立即领取', '领取', '签到')
def log(msg):
line = '[%s] %s' % (datetime.now().strftime('%m-%d %H:%M:%S'), msg)
print(line, flush=True)
try:
open(LOG, 'a', encoding='utf-8').write(line + '\n')
except Exception:
pass
def get_client():
root = auto.GetRootControl()
for c in root.GetChildren():
try:
if (c.Name or '') == 'WorkBuddy' and c.ClassName == 'Chrome_WidgetWin_1':
return c
except Exception:
pass
return None
def find_buttons(scope, kws, maxhits=8):
hits = []
def walk(ctrl, d):
if d > 20 or len(hits) >= maxhits:
return
try:
nm = ctrl.Name or ''
ct = ctrl.ControlTypeName
except Exception:
return
if nm and ct in ('ButtonControl', 'HyperlinkControl', 'TextControl') \
and any(k in nm for k in kws):
if any(b in nm for b in BAD_KWS):
return
try:
hits.append((nm[:40], ct, ctrl, ctrl.BoundingRectangle))
except Exception:
pass
return
try:
for c in ctrl.GetChildren():
walk(c, d + 1)
except Exception:
pass
walk(scope, 0)
return hits
def visible(r):
return r.width() > 8 and r.height() > 8 and r.top >= 0 and r.left >= 0
def click_ctrl(ctrl):
try:
r = ctrl.BoundingRectangle
sw, sh = auto.GetScreenSize()
if r.top < 0 or r.bottom > sh or r.left < 0 or r.right > sw:
try:
ctrl.GetScrollItemPattern().ScrollIntoView()
time.sleep(1.2)
except Exception:
return False
ctrl.Click()
return True
except Exception as e:
log('click fail: %s' % e)
return False
def step1_popup(win, wait_sec=60):
"""路径A: 等客户端弹窗「立即领取」"""
log('step1: wait popup claim button (%ds)' % wait_sec)
win.SetActive()
deadline = time.time() + wait_sec
while time.time() < deadline:
for nm, ct, ctrl, r in find_buttons(win, ('立即领取',)):
if visible(r) and click_ctrl(ctrl):
time.sleep(3)
return True
time.sleep(5)
log('step1: no popup')
return False
def step2_open_growth(win):
"""路径B: 个人菜单 -> 成长计划 -> 等 Edge 成长中心窗口"""
tgt = None
for attempt in range(2):
for nm, ct, ctrl, r in find_buttons(win, ('成长计划',), maxhits=20):
if visible(r) and r.height() > 15 and r.top < 900:
tgt = ctrl
break
if tgt:
break
try:
mi = win.MenuItemControl(SubName='个人')
if mi.Exists(3):
r = mi.BoundingRectangle
auto.Click((r.left + r.right) // 2, (r.top + r.bottom) // 2 + 5)
time.sleep(2)
except Exception:
pass
if not tgt:
log('step2: growth menu not found')
return None
if not click_ctrl(tgt):
return None
time.sleep(10)
root = auto.GetRootControl()
for c in root.GetChildren():
try:
if 'WorkBuddy' in (c.Name or '') and 'Edge' in (c.Name or ''):
time.sleep(4)
return c
except Exception:
pass
log('step2: growth-center Edge window not found')
return None
def step3_claim_on_web(edge):
"""在成长中心网页找领取按钮"""
log('step3: scan web page for claim buttons')
hits = find_buttons(edge, GOOD_KWS, maxhits=30)
for nm, ct, ctrl, r in hits:
if ct == 'TextControl':
continue
if click_ctrl(ctrl):
time.sleep(3)
return True
log('step3: no clickable claim button (probably already claimed)')
return False
def main():
auto.SetGlobalSearchTimeout(2)
log('=== wb_checkin start ===')
try:
win = get_client()
if win is None:
log('FATAL: WorkBuddy client window not found')
print('RESULT=FAIL', flush=True)
return
if step1_popup(win):
log('claimed via popup')
print('RESULT=SUCCESS', flush=True)
return
edge = step2_open_growth(win)
if edge is not None and step3_claim_on_web(edge):
log('claimed via web')
print('RESULT=SUCCESS', flush=True)
else:
print('RESULT=ALREADY', flush=True)
except Exception:
log('EXCEPTION: %s' % traceback.format_exc())
print('RESULT=FAIL', flush=True)
if __name__ == '__main__':
main()定时任务执行命令示例(Windows):
python C:\tools\wb_checkin.py >> C:\tools\checkin_cron.log 2>&1一条定时任务,两条兜底路径,三千积分按月到账。把它装上之后,你唯一还需要做的,是偶尔打开日志看看 AI 又一次默默替你干了活。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。