Files
live-hub-py/docs/HUYA_精英宝典-8.31-PY重新分析.md
T
2026-08-31 19:34:59 +08:00

129 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 虎牙精英宝典 HAR 重新分析(Python)
## 1. 样本与结论
| HAR | SHA-256 | entries | 结论 |
|---|---|---:|---|
| `手机扫码登录-pc直播间-1.har` | `bcb1e830bfc368c9029f85f90458b708dcf086993a79b833e8e544c65e5c679f` | 1947 | 扫码登录、PC 直播间初始化、登录态建立 |
| `pc直播间-精英宝典1.har` | `f8d13a837c477aa4dc55b27df6828ffb7840bbdcccf7c078f840164d62a00e07` | 580 | 精英宝典初始化、绑定、任务、奖品、积分、记录、商城前置 |
页面地址为 `https://zt.huya.com/b02faae1/pc/index.html`。活动固定业务参数为 `sid=2203``actId=25135`、绑定活动 `bActId=9271`、任务模块 `moduleId=20051`、游戏 `cjm`、组件 `gid/componentId=3203`
核心结论:协议是 WSS 二进制通道承载的 WUP/TAF RPCHTTP `cdnws.api.huya.com` 可作为现有 Python 客户端的兜底。样本没有捕获积分兑换成功请求、兑换详情响应或支付完成闭环,因此这些字段不能从 HAR 推测。
## 2. 传输层与帧解码
- 活动页主通道:`wss://wsapi.huya.com/?baseinfo=<动态值>`
- 直播间/绑定入口还使用 `wss://d35bf35c-ws.va.huya.com/?baseinfo=<动态值>`
- HTTP 兜底:`POST https://cdnws.api.huya.com/?baseinfo=<动态值>`,请求体为 WUP 包。
- HAR 的业务消息在 entry 的 `_webSocketMessages`,不是普通 HTTP entry body。
- WebSocket 帧前 6 字节是通道头(command、sequence),后续 body 再提取 WUPWUP body 从 `0x10 0x03` 字段开始。仓库的 `WssMessage.decode()``frame_decoder._extract_wup()``WupResponse.decode()` 可以复用。
- `launch.wsLaunch``mobileui.getConfig` 完成连接初始化;业务 WUP `requestId` 在同一会话中递增,不能写死 HAR 值。
## 3. 请求链
精英宝典 WebSocket entry 75 的可复现顺序如下:
1. `launch.wsLaunch` -> `mobileui.getConfig`
2. `GameBizUI.getQiWeiRelationByUid`(页面辅助信息)。
3. `webActUI.checkUserBindGameAccount(bActId=9271)`,返回和平精英、微信/QQ 平台、角色绑定状态。
4. 并行查询:`getActPrizeList(sid=2203)``getActInfo(actId=25135)``getActTaskDetail(actId=25135)`
5. `getActUserTaskDetail(userId, actId=25135)``getUserScore(sid=2203)`
6. 绑定流程:再次检查绑定 -> `huyauserui.getUserProfileBatch` -> `getLiveLinkParam(bActId=9271)` -> `confirmBindActAccount(bActId=9271)` -> 再次检查绑定。
7. 记录页:`getUserPrizeRecords(sid=2203)` -> `getEntityPrizeFieldMap` -> `getModuleAddress(moduleId=20051)`
8. 商城前置:`shopMiddleUI.getGoodsInfoV5`;确认页还调用 `getSupplierInfoV5``listPayChannelV5``checkHyProtocolV5``PlayMallUI.getMyPromotion``calcOrderPromotion`
9. 页面会重复刷新 `getActPrizeList``getUserScore`;轮询间隔由工作台自行配置,建议 10-30 秒,写操作后只做一次短轮询。
第一份 HAR 的扫码登录链为:
```text
GET /web/middle/2.6/.../https/...
POST /qrLgn/getQrId
GET /qrLgn/getQrImg?k=<qrId>&appId=5002
POST /qrLgn/tryQrLogin # stage=0 -> stage=1 -> success
POST /web/cookie/verify
```
成功登录后得到的 UID、Cookie、`baseinfo` 必须传入同一个 WSS/HTTP 会话。二维码 ID、requestId、context、biztoken、guid、`udb_cred``sdid`、时间戳和签名均为动态值,报告不固化样本机密值。
### 参数分类
| 参数 | 类型 | Python 处理 |
|---|---|---|
| `sid/actId/bActId/moduleId/gid` | 业务参数 | 配置项,默认值只对应本次页面 |
| `uid`、游戏账号/角色 | 用户输入或前序响应 | 从当前登录态或绑定响应读取 |
| Cookie、`baseinfo`、WSS session | Token/Session | `HuyaHttpClient` 运行时构造并保持 |
| `qrId/requestId/context/traceId` | 随机/请求序号 | 登录和 RPC 运行时生成 |
| `t/code/sig``biztoken``udb_cred``sdid` | 动态签名/认证 | 只转发前序响应或 Cookie;算法未闭合,不重算 |
| `startTime/endTime/leftNum/isCanExchange` | 服务端状态 | 每次查询覆盖本地快照,不写死 |
HTTP 请求保留 `User-Agent``Origin``Referer``Content-Type: application/octet-stream``Accept-Language``Host``Content-Length``Connection` 由 HTTP 库生成。WSS 的 `baseinfo` query 和二进制 body 由会话客户端生成,不复制浏览器历史头。
## 4. 业务响应复核
### 活动信息
`getActInfo``status=200``actId=25135`,名称“活动+购买任务”,时间戳 `1782662400..1790783999`,任务模块 `20051`,外部任务活动 `17096`,游戏 `cjm`,组件 `3203``17096` 与绑定用的 `9271` 是不同字段,代码中必须分开命名。
### 奖品列表
`getActPrizeList` 在 entry 75 的多次响应均返回 **29 项**、2 个分类:`91=限量返场`11 项)和 `83=精英专享`18 项)。示例:
| pid | 名称 | 积分 | 分类 |
|---:|---|---:|---:|
| 13161 | 破片手榴弹-粉粉猫爪大礼包 | 3600 | 91 |
| 13163 | 烟雾弹-猫咪绅士大礼包 | 3600 | 91 |
| 13167 | 套装-幸运萌趣趣 | 1980 | 91 |
| 13165 | 套装-奇妙萌趣趣 | 688 | 91 |
| 13169 | 套装-幸福萌趣趣 | 1680 | 91 |
| 12873 | 套装-青涩年华 | 488 | 83 |
| 12867 | 套装-雪山精英 | 600 | 83 |
| 12879 | 套装-浪漫波比 | 1280 | 83 |
| 12865 | 幸运币礼包(大) | 900 | 83 |
完整结构还包含 `id/sid/name/score/type/img/sort/frequency/frequencyLimit/num/status/percent/newScore/tags/leftNum/isShowNum/usedNum/goodType/detailImg/detailDesc/whiteUser/commonPrizeId/updateTime/isCanExchange/exchangeStartTime/exchangeEndTime/startTimeSlot/endTimeSlot/isTodayLimit/isUserLimit`。库存、排序和可兑换状态在重复轮询中变化,不能硬编码;工作台应以最新响应覆盖快照。
### 任务与用户进度
`getActTaskDetail` 返回 6 个任务:
- 购买精英令 *100,奖励 10000 分,SPU `hy-5874270`
- 购买精英令 *10,奖励 1000 分,SPU `hy-5874269`
- 购买精英令 *1,奖励 100 分,SPU `hy-5879346`
- 购买精英徽章,奖励 10 分,SPU `hy-5872824`
- 每天观看和平精英直播 10 分钟,奖励 2 分,任务类型 56。
- 订阅和平精英福利提醒,奖励 5 分,任务类型 68。
`getActUserTaskDetail` 的每项至少有 `actId/taskId/taskStatus/prizeStatus/taskValue/taskCount/prizeCount/subTaskDetail`,它是展示任务进度、完成和领取状态的来源。
### 积分
响应字段顺序为 `status/msg/gainScore/usedScore/newGainScore/newUsedScore/score/isOpenExchangeTip`。样本值为 `4200,4200,4200,4200,0,0`;页面逻辑优先使用 `max(0, newGainScore-newUsedScore)`,所以当时可用积分为 **0**,不能把任意一个累计字段直接当余额。
### 绑定、记录与地址
- 绑定响应显示游戏“和平精英”,账号平台可为微信或 QQ,`isBindAccount``isBindRole``isNeedActCheck``changeBindTime` 随状态变化。
- `getLiveLinkParam` 返回 `actId=17096``gameIdList=cjm``livePlatId=huya`、动态 `t/code/sig`。样本不足以闭合 `code/sig` 算法,不实现猜测签名。
- `confirmBindActAccount` 样本为 `status=200,msg=请求成功`
- `getUserPrizeRecords` 返回 2 条历史记录,字段包括 `id/name/score/createTime/status/type/isReal/newScore/account/code/commonPrizeType/commonPrizeStatus/orderId/img/goodType/prizeId/recordId/commonPrizeExchangeStatus/commonPrizeId/prizeExtraParam/ymd/commonPrizeMsg`
- `getEntityPrizeFieldMap` 给出实体奖品字段映射:模块 1 为姓名/手机/地址,模块 38 为 QQ,模块 39 为姓名/手机;`getModuleAddress(moduleId=20051)` 返回 `status=201,msg=找不到地址`
## 5. Python 实现边界
仓库现有 `core/huya/http_client.py` 已实现 WUP/TAF、会话 Cookie、积分、奖品列表、记录、任务、绑定、直播链接和商城方法;新增示例见 [`scripts/huya_elite_client.py`](../scripts/huya_elite_client.py)。示例不读取 HAR,运行时从环境变量读取 UID/Cookie,调用顺序为:活动信息/任务/用户任务/绑定/奖品/积分/记录,写操作前重新查询奖品详情。
推荐状态机:
```text
登录态 -> getActInfo/getActTaskDetail
-> checkBind/getActPrizeList/getActUserTaskDetail/getUserScore
-> (用户确认后) getActPrizeDetail -> scoreExchangePrize
-> getUserScore/getActPrizeList/getUserPrizeRecords 回查
```
兑换必须二次校验 `isCanExchange`、活动时间、库存、频次、今日/用户限制和可用积分。`getActPrizeDetail``scoreExchangePrize` 成功响应以及地址写入尚未出现在样本中,客户端应把它们作为显式待补接口,而不是猜测字段。
## 6. 尚缺证据与补抓清单
当前 HAR 未闭合:`getActPrizeDetail` 响应、`scoreExchangePrize` 成功请求/响应、`addModuleAddress``createOrderV5``payOrderSubmitV5`、支付完成后的订单状态和宝典开通字段。需要重新抓“点击兑换”和“点击开通宝典至支付完成”的完整操作,并保留 Initiator、页面 JavaScript 和同一登录态。