WorkBuddy 积分看板
抓取 WorkBuddy 官方积分消耗明细,生成并持续更新实时 HTML 看板。
适用场景
- 用户要查看 WorkBuddy 积分消耗、用量明细、账单
- 用户要求"更新积分看板"、"抓取官方积分数据"
- 用户粘贴官方页面地址要求爬取积分数据
核心事实(重要,避免返工)
- 官方页面:
https://www.workbuddy.cn/profile/plans-usage(需登录态,通过 CDP 连用户 Chrome 访问) - 官方数据是逐条 Request 粒度:每条含 时间/积分消耗/模型/客户端/Request内容/requestId,精确到分钟
- 官方只保留近 30 天:更早数据页面查不到,只能靠本地 SQLite 会话聚合兜底
- 本地 SQLite(
~/.workbuddy/workbuddy.db的session_usage表)只有会话级聚合, 且updated_at是本地同步时间而非真实消耗时间——绝不能用它按天统计积分(会虚高/错位)。 仅作官方数据缺失时的降级源,且必须按sessions.created_at归属日期。 - 日期边界:官方"今天/7天/30天"按钮按 UTC 时区算"今天",GMT+8 凌晨会看到昨天数据。 增量抓取时起始日 = 本地已有数据最大日期(含当天)——当天数据仍在增长,从下一天开始会漏数据。
前置条件
- 用户 Chrome 已开启远程调试:
--remote-debugging-port=9222 - CDP proxy 已就绪:
输出node "$HOME/.workbuddy/skills/web-access/scripts/check-deps.mjs" --browser chromeproxy: ready后继续。若browser: needs decision,用--browser chrome临时指定。 - 用户已在浏览器登录 workbuddy.cn(登录态天然携带)。
执行流程
第一步:抓取官方数据
直接运行随附脚本(已内置日期边界/去重/分页/虚拟滚动处理):
python3 "$HOME/.workbuddy/skills/workbuddy-credit-dashboard/scripts/scrape_official.py" \
--start 2026-07-17 --end 2026-08-15 # 指定范围
或增量(默认:从已有数据最大日期抓到今天):
python3 "$HOME/.workbuddy/skills/workbuddy-credit-dashboard/scripts/scrape_official.py"
脚本自动完成:
- 打开/复用 plans-usage 页面
- 设置日期范围(改日期输入框 → Enter 确认)
- 确保分页 50条/页(页面可能残留 10条/页,必须检查切换)
- 虚拟滚动列表滚动到底触发整页渲染
- 分页抓全 → 按 requestId 去重合并 → 写
data/official_usage.json+ 导出 CSV
第二步:看板数据接入
看板服务 server.py 已实现官方 JSON 优先、本地 SQLite 降级:
- 有
data/official_usage.json→ 用官方逐条数据(source: "official") - 无 → 回退本地
session_usage(按 sessions.created_at 归属日期)
启动看板:
python3 server.py 8765 # 后台运行
浏览器访问 http://127.0.0.1:8765。服务每次请求实时读文件,改完数据/页面无需重启。
第三步:若需从零搭建看板
若目标环境没有现成看板,用本技能 assets/dashboard/ 下的模板:
assets/dashboard/server.py— 数据服务(官方 JSON 优先 + SQLite 降级)assets/dashboard/index.html— 深色科技风看板(KPI/柱状图+平均线/模型分布/明细表)assets/dashboard/scrape_official.py— 抓取脚本(与 scripts/ 下同一份)
复制到目标目录后按第二步启动即可。
关键经验(踩坑记录)
抓取页面操作
- 页面是 React SPA,
document.body.innerText能看到内容但必须等渲染完成, 否则 request 标题全是 "-"(wait_rows已处理)。 - 日期范围设置:点击
.request-usage-table__date-range→ 改两个.t-date-range-picker input.t-input__inner的值(用原生 value setter + input/change 事件)→ 对结束日期输入框派发 Enter。 直接radio.click()对 TDesign 组件无效,需点击 label 或文本元素。 - 分页大小:
.request-usage-table__page-size可能显示 10条/页,必须切换为 50条/页, 否则 686 条要翻 69 页且虚拟列表不加载。 - 虚拟滚动:
.request-usage-table__body是虚拟滚动容器,抓当前页前必须scrollTop = scrollHeight。 - 下一页按钮:
.request-usage-table__page-arrow[aria-label="下一页"]。
数据口径
- 官方 8-15 的"几十点"≈ 78-102 积分(随时间增长),本地 SQLite 会话聚合算出来会有 ±20-60 偏差, 以官方为准。
- requestId 是去重唯一键;同一次抓取若中断重跑,靠它幂等合并。
看板实现
- 柱状图平均线必须用像素坐标系与柱子对齐:绘图区 = 容器高 − 顶部留白 − 日期标签占位
(本模板 AREA = 210 − 8 − 41 = 161px),柱高和平均线 bottom 都用
值/max × AREA的像素值, 否则百分比基准不一致导致平均线错位。 - 平均线标签放左侧(
left:0),数值 = 当前范围均值(与 KPI 一致,剔除单日最大值)。 - 会话级明细默认按日期+时间降序(最新在前),日期/时间列排序联动(组合字符串比较)。
- 模型分布悬停显示:模型名/积分/占比/调用次数(后端 models 需带 count 字段)。
输出
data/official_usage.json— 全量去重后的官方逐条数据(看板数据源)官方积分账单-YYYYMMDD至YYYYMMDD-YYYYMMDD.csv— 可 Excel 打开的账单- 看板页面实时反映最新数据
注意
- 抓取用 CDP 连用户浏览器,操作的是后台新 tab,完成后关闭自己创建的 tab,不动用户原有 tab。
- 发布/对外分享任何包含用户积分明细的文件前,先确认数据隐私。
微信扫一扫