实现虎牙密码登录

This commit is contained in:
yml2213
2026-07-05 11:12:36 +08:00
parent 5534293ed1
commit 2824c5a54c
9 changed files with 657 additions and 39 deletions
+55 -9
View File
@@ -222,6 +222,12 @@ class HuyaVerificationSolver:
self.strategy_url = strategy_url
if not self.url_param_map.get("param"):
raise HuyaVerificationError("虎牙验证链接缺少 param")
logger.debug(
"虎牙验证参数: sceneType={}, mobile={}, param长度={}",
self.scene_type,
self.url_param_map.get("mobile", ""),
len(self.url_param_map.get("param", "")),
)
def _restore_slider_background(self, bg_bytes: bytes, segment: str, huyapk: str) -> bytes:
recover_list = self.js_ctx.call("get_regoin_arr", segment, huyapk)
@@ -236,6 +242,7 @@ class HuyaVerificationSolver:
return output.getvalue()
def _get_track_point(self, url: str, payload: dict):
logger.debug("虎牙验证获取图片: {}", url)
result = self._request_json("post", url, json=payload)
if result.get("returnCode") != 0 or not result.get("data", {}).get("code"):
raise HuyaVerificationError(f"获取验证码图片失败: {result}")
@@ -254,7 +261,9 @@ class HuyaVerificationSolver:
yolo_x = int(slider_box[0] - 13)
opencv_x = self._opencv_slider_x(tip_bytes, restored_bg)
if abs(opencv_x - yolo_x) < 10:
logger.debug("虎牙滑块识别距离: yolo={}, opencv={}", yolo_x, opencv_x)
return int((opencv_x + yolo_x) / 2)
logger.debug("虎牙滑块识别距离: yolo={}, opencv={}, 使用yolo", yolo_x, opencv_x)
return yolo_x
logger.info("虎牙验证类型: 点选")
@@ -334,23 +343,60 @@ class HuyaVerificationSolver:
return self._submit_verify(url, payload)
def _submit_verify(self, url: str, payload: dict) -> dict:
logger.debug("虎牙验证提交: {}", url)
body = json.dumps(payload, separators=(",", ":"))
result = self._request_json("post", url, params={"lock": "true"}, data=body)
return result.get("data") or result
data = result.get("data") or result
if isinstance(data, dict):
logger.debug(
"虎牙验证提交结果: authId={}, nextAuthUrl={}",
bool(data.get("authId")),
bool(data.get("nextAuthUrl")),
)
return data
def _solve_current_strategy(self) -> dict:
"""提交当前 strategy_url 对应的验证。"""
config_payload = self._build_common_payload({"cTuIndex": 0})
config = self._request_json("post", "https://udbrtt.huya.com/auth/client/config3", json=config_payload)
try:
gurl = config["data"]["gurl"]
vurl = config["data"]["vurl"]
dx_js = config["data"]["js"]
except KeyError as exc:
raise HuyaVerificationError(f"config3 取参失败: {config}") from exc
config = {}
gurl = ""
vurl = ""
dx_js = ""
for index in range(2):
logger.debug("虎牙验证获取config3 ({}/2)", index + 1)
config = self._request_json("post", "https://udbrtt.huya.com/auth/client/config3", json=config_payload)
data = config.get("data") if isinstance(config.get("data"), dict) else {}
gurl = str(data.get("gurl") or "")
vurl = str(data.get("vurl") or "")
dx_js = str(data.get("js") or "")
logger.debug(
"虎牙config3返回: returnCode={}, desc={}, gurl={}, vurl={}, js长度={}",
config.get("returnCode"),
config.get("description") or config.get("message") or "",
bool(gurl),
bool(vurl),
len(dx_js),
)
if gurl and vurl and dx_js:
break
if index == 0 and self.url_param_map.get("sceneType") != "4":
self.url_param_map["sceneType"] = "4"
self.scene_type = "4"
config_payload = self._build_common_payload({"cTuIndex": 0})
logger.debug("虎牙config3取参不完整,改用旧流程sceneType=4重试")
time.sleep(0.3)
if not gurl or not vurl or not dx_js:
raise HuyaVerificationError(
"config3取参失败: "
f"returnCode={config.get('returnCode')}, "
f"description={config.get('description') or config.get('message') or ''}, "
f"gurl={bool(gurl)}, vurl={bool(vurl)}, js={bool(dx_js)}"
)
self._compile_js(dx_js)
point = self._get_track_point(gurl, config_payload)
point_payload = self._build_common_payload({"ver": 5})
point = self._get_track_point(gurl, point_payload)
logger.debug(f"虎牙验证识别结果: {point}")
if isinstance(point, list):
return self._send_click_verify(vurl, point)