网易云音乐有个「免费听歌」活动:每天看几次广告,就能领到 VIP 歌曲畅听时长。手机 App 里点几下就有,但每天手动点太麻烦,于是写了个脚本全自动领取,每天 9 点定时跑,白嫖 2 小时畅听。

技术难点

网易云现在的接口不是普通 HTTPS 请求,而是 xeapi 加密协议(X25519 密钥协商 + AES-GCM 加密),请求体和响应体都是密文,直接抓包看到的只有几个加密参数。

逆向思路参考了 NeteaseCloudMusicApiEnhanced 这个开源项目,把它的 xeapi 加密/解密模块单独抽出来复用:

  1. 先请求公钥接口,拿到 X25519 公钥(带签名验证)
  2. 之后所有业务请求走 interface3.music.163.com/xeapi/...,请求体用公钥协商后的会话密钥加密
  3. 响应体用服务器下发的 x-encr-ssid / x-encr-sskey 解密

关键发现:为什么之前领到的是「低保」

第一版脚本拿到广告后立刻调领取接口,结果每次只给 14、12、10……递减的分钟数,最后直接 0 分钟。服务端明摆着在说:你没看广告

翻抓包数据发现广告响应里有两个关键字段:

  • rightsGainMethod: 4 — 领取方式,之前用的 2 是错的
  • clickStayTime: 6 — 广告需要停留 6 秒才能领

改成「拿广告 → 等 6 秒 → 再领」后,每次稳定 30 分钟,4 次正好 2 小时。

代码质量修补

跑通之后顺手做了轮代码审查,修了几个隐患:

问题 修复
clickStayTime 取错层级,靠默认值兜底 改为从 generalRightsInfo.clickStayTime
creativeType 硬编码 36 改为从广告响应动态取
extJson JSON 解析无保护 加 try-catch 兜底
网络请求失败直接中断 withRetry 自动重试 2 次
加密库路径硬编码绝对路径 改为相对 __dirname 解析
错误信息只有 message 补上调用栈前几行

定时任务

用 Hermes 的 cron 每天 09:00 跑一次,no_agent 模式直接执行脚本,领取结果原样推送到微信。cookie 存本地文件,过期了换一下就行。

文件清单

  • free_listen.js — 主脚本(xeapi 加密 + 领取逻辑)
  • free_listen.sh — 包装脚本(注入 cookie 环境变量)
  • netease-api/ — 复用的 xeapi 加密模块

📝 本文由 AI 助手群晖仕辅助生成