web-signer 通用自动签到
配置驱动的浏览器自动签到引擎:Playwright-core + 系统 Edge(channel: msedge) + 每站独立持久化 Profile。
适用:有人机验证(滑块/点选/Cloudflare)或扫码登录,导致 QD 等纯 HTTP 框架无法签到的网站。
核心思路:人机验证只发生在登录环节 → 首次有头模式人工过一次验证 → 登录态(cookie + localStorage)存入 Profile 长期复用 → 之后无头全自动。
使用
cd ~/.workbuddy/skills/web-signer/scripts
npm install # 首次,仅 playwright-core,复用系统 Edge,无需下载浏览器
node web_signer.js <site> login # 首次/失效后:有头模式,人工完成验证登录(自动检测并关窗)
node web_signer.js <site> # 日常签到(无头),输出 JSON
node web_signer.js <site> --head # 有头签到(调试用)
node probe.js <site> [path...] # 站点探测:dump 登录态/cookie/签到元素/API 请求
node probe.js <site> --click "签到" # 点击签到元素并捕获触发的 XHR(接入新站必用)
node probe.js --url https://xxx.com/ # 无配置直接探测(无登录态)
退出码:0=成功或已签到;2=登录态失效(需重新 login);1=其他失败。
接入新站点流程(重要)
- 先写一份最小配置(baseUrl / loginUrl / loginCheck),让
probe.js能复用 Profile node web_signer.js <site> login—— 人工登录一次(账密、扫码、过验证都在这一步)
- ⚠️ 若 loginCheck 还没配准,login 会一直轮询到超时(10 分钟)。不要强杀进程(会丢 localStorage 里的 token),让它自然结束即可,登录态其实已经落盘node probe.js <site> --click "签到"—— 抓真实签到行为,据此确定sign.type- 补全配置后
node web_signer.js <site>无头实测(当日首签 + 重复签到两种场景) - 建 WorkBuddy automation 定时任务(rrule
FREQ=DAILY;BYHOUR=0;BYMINUTE=N,各站错开分钟数)
四种签到模式(sign.type)
| 模式 | 适用 | 说明 |
|---|---|---|
fetch |
签到是干净的 XHR,且无签名校验 | 在页面上下文内发请求,与网站 JS 行为一致。最快 |
visit |
访问签到页即自动完成签到 | 导航到 sign.url,等待后用 sign.verify 判定 DOM 标记 |
click |
需要点按钮才触发 | 点 sign.selector |
js |
多步表单签到(选心情→选模式→点提交) | 在页面上下文执行 sign.js 一段 JS 完成全部操作,适合 Discuz! dsu_paulsign 等多步签到插件 |
选 fetch 的前提:先用 probe 在页面里裸 fetch 试一次。若返回"时钟错误"、"签名错误"、errorcode 之类,说明 API 有时间戳/签名校验(如 itsk),必须改用 visit 或 click,让网站自己的 JS 去发请求。
站点配置字段(sites/<site>.json)
| 字段 | 必填 | 说明 |
|---|---|---|
displayName |
站点显示名 | |
baseUrl |
✅ | 站点首页(结尾斜杠自动补全) |
loginUrl |
✅ | 登录页路径(相对 baseUrl 或绝对 URL) |
homeUrl |
登录态检测页,默认首页 | |
profileDir |
Edge Profile 目录,默认 scripts/profiles/<site> |
|
apiHost |
独立 API 域名(probe.js 抓包用,如 api.itsk.com) |
|
loginCheck |
✅ | 登录判定,见下方「判定器」 |
loginCheck.anonymousPattern |
text 型必填 | 未登录特征正则(如 请先登录) |
sign.type |
✅ | fetch / visit / click |
sign.url |
fetch/visit | 请求或页面路径 |
sign.method/headers/body |
fetch | 与网站自身 JS 完全一致 |
sign.waitMs |
visit | 页面加载后等待毫秒,默认 6000 |
sign.verify |
visit 推荐 | 签到成功标记,判定器格式 |
sign.selector/afterClickWaitMs |
click | 按钮选择器 |
sign.successCode |
成功 code(统一按字符串比较),默认 "0" |
|
sign.alreadyPattern |
返回信息中"已签到"特征正则 | |
signedCheck |
推荐 | 签到前判定已签(避免重复请求),判定器格式,额外支持 url(在指定页面检查)和 waitMs |
infoUrl |
info 抓取前跳转的页面;设为 null 表示不跳转(停留在签到页读) |
|
info[] |
签到后抓取的信息 {key, ...判定器} |
|
pageSettleMs |
页面加载后额外等待毫秒(慢站/SPA 调大到 4000+) | |
referer |
导航签到页时设置的 referer(相对路径或绝对 URL),模拟从首页点击进入,规避直接访问触发风控(如飞牛阿里云 ESA 滑块) |
判定器(loginCheck / signedCheck / sign.verify / info 通用)
{ "type": "text", "selector": "#sign_title", "signedPattern": "已签到" } // 默认,取文本正则匹配
{ "type": "exists", "selector": ".prize-item.toddy-signed" } // 元素存在即命中
{ "type": "js", "js": "localStorage.getItem('isLogin')==='true'" } // JS 表达式 truthy 即命中
SPA / Token 制站点(Nuxt、Vue、React)优先用 js 读 localStorage 判登录态,比找 DOM 稳。
OCR 自动识别 WAF 验证码(v1.3.0 新增,v1.3.1 支持多 Provider)
部分站点(如吾爱破解)签到时会跳转到 WAF 图形验证码页(如 waf_text_verify.html)。引擎支持配置百度 OCR 自动识别并提交:
{
"ocr": {
"apiKey": "你的百度OCR API Key",
"secretKey": "你的百度OCR Secret Key"
},
"waf": {
"verifyUrlPattern": "waf_text_verify\\.html",
"captchaImageSelector": "#Image1",
"captchaInputSelector": "input[name=captcha]",
"submitSelector": ".code-btn",
"maxRetries": 3,
"afterSubmitWaitMs": 5000,
"afterWaitMs": 8000
}
}
工作流程:签到动作执行后,如果当前 URL 匹配 verifyUrlPattern,引擎自动下载验证码图片 → 调用百度 OCR → 填充输入框 → 提交 → 原签到流程继续。
ocr和waf同时配置才会启用。OCR 密钥推荐用环境变量提供:BAIDU_OCR_API_KEY/BAIDU_OCR_SECRET_KEY(优先级高于ocr.apiKey/ocr.secretKey),可避免密钥写进可分享的sites/*.json/templates/*.jsonwaf.afterWaitMs是 WAF 通过后等待页面稳定的时间(52pojie 会跳转到 task draw 页再跳回首页)- 百度 OCR 使用
accurate_basic接口,免费额度通常够用
验证码识别 Provider(v1.3.1 新增)
WAF 图形验证码识别支持可切换的 Provider,通过站点配置 captcha.provider 选择,默认 baidu(即原百度 OCR)。
小笨羊(xiaobenyang)
调用小笨羊 OCR 接口识别验证码,流程与 SkillHub 官方技能 xby-ocr-captcha 完全一致(POST https://mcp.xiaobenyang.com/api,请求头 XBY-APIKEY + func + mcpid,body 传图片 base64),支持文本验证码。底层与 SkillHub 的 captcha 验证码识别技能是同一套 API——两者共用同一个 key,即「联动」该技能。
{
"captcha": {
"provider": "xiaobenyang",
"mcpId": "1825936344787978",
"tool": "ocr_captcha_for_data_base64",
"baseUrl": "https://mcp.xiaobenyang.com"
}
}
- 密钥:环境变量
XBY_APIKEY(与xby-ocr-captcha/captcha技能共用;装好技能并配好 key 后 web-signer 直接可用)。也可写在captcha.apiKey(不推荐,会进配置文件)。注意:小笨羊按 key 计费,使用前需保证账户有积分,否则返回API KEY的积分不足。 mcpId:默认1825936344787978(即小笨羊「验证码识别OCR」服务);其他小笨羊 MCP 在此覆盖即可。tool:默认ocr_captcha_for_data_base64(参数dataBase64,文本验证码);另有ocr_captcha(参数dataUrl,传图片链接)。- 识别失败(积分不足、图片异常等)会打印
[ERROR] 小笨羊识别失败: <errMsg>或[ERROR] 小笨羊未能解析出验证码文本: ...原始响应。
已接入站点
| site | 程序 | 签到方式 | 定时 | 备注 |
|---|---|---|---|---|
pan1 |
XiunoBBS + tt_sign + Cloudflare | fetch ?my-sign.htm |
00:25 | 账密登录,cookie 制登录态 |
itsk |
Nuxt3 自研 + api.itsk.com REST | visit /activity/sign --head |
00:01 | 微信扫码登录,cookie sl-session;无头模式被反爬风控返回 -1100 伪装时钟错误,必须 --head 有头模式;签到活动期 2026-07-27~11-29 |
fnclub |
Discuz! X + zqlj_sign 插件 | click plugin.php?id=zqlj_sign |
00:10 | 阿里云 ESA 滑块风控:直接访问签到页触发滑块,配置 referer: "portal.php" 模拟从首页进入可规避 |
52pojie |
Discuz! X + 任务系统签到 | click home.php?mod=task&do=apply&id=2 |
09:00 | WAF 图形验证码;已接入百度 OCR 自动识别 |
tampermonkey |
Discuz! X + dsu_paulsign 签到插件 | js dsu_paulsign-sign.html --head |
00:40 | 多步表单签到:JS 选心情(kx=开心)+模式(2=快速选择)+点 qdtb.gif 提交;签到服务台在 #ct .mn p 提取状态 |
站点模板 / 换机迁移
scripts/sites/*.json 只包含站点接入知识(URL、选择器、判定逻辑),不包含密码,也不应包含登录态。你可以把它当成模板发给其他机器或智能体,对方导入后只需重新登录一次即可使用。
导出模板
node export-template.js pan1 # 生成 templates/pan1.json
node export-template.js itsk # 生成 templates/itsk.json
node export-template.js fnclub # 生成 templates/fnclub.json
node export-template.js 52pojie # 生成 templates/52pojie.json
node export-template.js pan1 --out /path/to/share/pan1.json
导出的模板会自动去掉 profileDir,只保留站点接入逻辑。
导入模板
# 对方收到模板后,在 web-signer/scripts 目录执行:
node import-template.js pan1 # 从 templates/pan1.json 导入
node import-template.js /path/to/pan1.json # 从任意路径导入
# 然后做一次人工登录,登录态会落到 profiles/<site>
node web_signer.js pan1 login
导入时会自动把 profileDir 重置为本地默认路径,避免旧机器绝对路径失效。
手动分享也可以
直接复制 templates/*.json 或 sites/*.json(两者都不含敏感信息)给对方即可。唯一规则:对方拿到后必须执行一次 login 来生成自己的 Profile,因为登录态(cookie/localStorage/token)不能跨机器迁移。
运维注意
- 每个站点的 Profile 目录即登录态,删目录 = 退出登录
- Profile 合并架构:多个站点可共用
profiles/_shared/目录(cookie 按域名天然隔离),方便用有头浏览器一次性查看所有站点状态;代价是失去故障隔离 + 同一时间只能一个进程持有 profile(定时任务必须错开时间串行) - --head 有头模式:反爬站点(如 itsk 对无头返回伪装错误)必须用
--head;非反爬站点保持无头(凌晨不弹窗) - 定时任务返回退出码 2 时,提示用户说"XX 重新登录"即可
- 不要用 requests/axios 纯 HTTP 方案替代:有 Cloudflare 或签名校验的站会失败
- 新增站点只需加 JSON,不要复制引擎代码
- 同一个 Profile 不能被两个进程同时打开,跑脚本前确认没有残留 node/msedge 进程
- modeLogin 非侵入式检测:登录轮询时不导航不刷新,只在当前页面检查登录标记,避免刷新页面导致用户无法点击登录按钮
- 临时探测脚本用完即删,统一走
probe.js
文件
scripts/web_signer.js- 通用引擎(唯一签到代码)scripts/probe.js- 通用站点探测器(接入新站用)scripts/export-template.js- 站点配置导出为模板scripts/import-template.js- 从模板导入站点配置scripts/sites/*.json- 站点配置(每站一个)templates/*.json- 去本地化的站点模板(可分享)scripts/profiles/<site>/- 各站 Edge Profile(自动生成,含登录态)