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

8.9 KiB
Raw Blame History

虎牙精英宝典 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=2203actId=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.wsLaunchmobileui.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;确认页还调用 getSupplierInfoV5listPayChannelV5checkHyProtocolV5PlayMallUI.getMyPromotioncalcOrderPromotion
  9. 页面会重复刷新 getActPrizeListgetUserScore;轮询间隔由工作台自行配置,建议 10-30 秒,写操作后只做一次短轮询。

第一份 HAR 的扫码登录链为:

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_credsdid、时间戳和签名均为动态值,报告不固化样本机密值。

参数分类

参数 类型 Python 处理
sid/actId/bActId/moduleId/gid 业务参数 配置项,默认值只对应本次页面
uid、游戏账号/角色 用户输入或前序响应 从当前登录态或绑定响应读取
Cookie、baseinfo、WSS session Token/Session HuyaHttpClient 运行时构造并保持
qrId/requestId/context/traceId 随机/请求序号 登录和 RPC 运行时生成
t/code/sigbiztokenudb_credsdid 动态签名/认证 只转发前序响应或 Cookie;算法未闭合,不重算
startTime/endTime/leftNum/isCanExchange 服务端状态 每次查询覆盖本地快照,不写死

HTTP 请求保留 User-AgentOriginRefererContent-Type: application/octet-streamAccept-LanguageHostContent-LengthConnection 由 HTTP 库生成。WSS 的 baseinfo query 和二进制 body 由会话客户端生成,不复制浏览器历史头。

4. 业务响应复核

活动信息

getActInfostatus=200actId=25135,名称“活动+购买任务”,时间戳 1782662400..1790783999,任务模块 20051,外部任务活动 17096,游戏 cjm,组件 320317096 与绑定用的 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,isBindAccountisBindRoleisNeedActCheckchangeBindTime 随状态变化。
  • getLiveLinkParam 返回 actId=17096gameIdList=cjmlivePlatId=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。示例不读取 HAR,运行时从环境变量读取 UID/Cookie,调用顺序为:活动信息/任务/用户任务/绑定/奖品/积分/记录,写操作前重新查询奖品详情。

推荐状态机:

登录态 -> getActInfo/getActTaskDetail
       -> checkBind/getActPrizeList/getActUserTaskDetail/getUserScore
       -> (用户确认后) getActPrizeDetail -> scoreExchangePrize
       -> getUserScore/getActPrizeList/getUserPrizeRecords 回查

兑换必须二次校验 isCanExchange、活动时间、库存、频次、今日/用户限制和可用积分。getActPrizeDetailscoreExchangePrize 成功响应以及地址写入尚未出现在样本中,客户端应把它们作为显式待补接口,而不是猜测字段。

6. 尚缺证据与补抓清单

当前 HAR 未闭合:getActPrizeDetail 响应、scoreExchangePrize 成功请求/响应、addModuleAddresscreateOrderV5payOrderSubmitV5、支付完成后的订单状态和宝典开通字段。需要重新抓“点击兑换”和“点击开通宝典至支付完成”的完整操作,并保留 Initiator、页面 JavaScript 和同一登录态。