找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2508

积分

0

好友

342

主题
发表于 13 小时前 | 查看: 1| 回复: 0

在使用浏览器、requestsaiohttpscrapy 等工具访问B站视频页面时,很多人可能会遇到一个特定的HTTP状态码:412 Precondition Failed

这并非普通的网络错误,而是B站风控系统明确拒绝请求的信号。其表现形式通常包括直接返回412状态码、页面空白或跳转失败,并且同一IP地址在短时间内频繁触发此状态的可能性很高。

412状态的本质是什么?

简单来说,412意味着你的请求被系统判定为“非正常用户”行为。B站服务端会对请求进行一系列行为判定,例如:

  • 用户代理(UA)是否合理
  • 请求频率是否过高
  • IP地址是否来自数据中心或代理
  • Cookie及用户行为链是否完整

一旦命中风控规则,系统不会直接封禁IP,而是会触发一个验证码挑战流程

B站412错误页面截图

从挑战到突破口:Set-Cookie中的令牌

当触发412响应时,响应头中会包含一个关键字段:

Set-Cookie: X-BILI-SEC-TOKEN=xxxxx

这个 X-BILI-SEC-TOKEN 便是后续逆向分析的核心切入点。我们需要从视频页面请求的响应中提取它。

def parse_412_token(set_cookie: str):
    """
    从 Set-Cookie 中提取 captcha token
    """
    try:
        token = set_cookie.split(';')[0].split(',')[1]
        return token
    except Exception:
        return None

注意:此令牌并非随机字符串,而是一个JWT-like结构,其中间段是Base64编码的数据。

解码令牌:获取验证码参数

令牌结构大致为 xxxx.payload.xxxx,我们关心的是中间的 payload 部分。

def decode_captcha_payload(token: str):
    """
    base64 解密 token 中的 q, r
    """
    base64_text = token.split('.')[1]
    decrypt_json = json.loads(b64decode(base64_text + "=="))
    return decrypt_json.get("q"), decrypt_json.get("r")

解码后,可以获得两个关键字段:

  • q:计算前缀
  • r:目标哈希值

至此可以明确:B站的412挑战并非传统的图形验证码,而是一道基于算力的验证题。

核心验证逻辑:暴力但有效的哈希碰撞

逆向分析后发现,其验证逻辑本质是寻找一个非负整数 i,使其满足以下等式:

sha256(q + i) == r

其中 i 的取值范围是有限的。

核心求解代码如下:

def solve_captcha(a, b):
    def sha256(data: str) -> str:
        return hashlib.sha256(data.encode()).hexdigest()
    limit = 0x4C4B40  # 约 500 万
    for i in range(limit):
        if sha256(a + str(i)) == b:
            return i
    return None

这段代码逻辑清晰,没有复杂的混淆或花指令。它更像是一种轻量级的“客户端真实性”验证,通过要求客户端进行一定量的计算来区分正常浏览器和简单爬虫脚本。

验证码计算结果DEBUG日志

提交验证并获取通行证

计算出结果 i 后,需要将其提交给B站的校验接口。

CAPTCHA_URL = "https://security.xxxx.com/th/captcha/cc/check"
data = {
    "token": token,
    "result": result
}

服务器验证通过后,会返回一个新的令牌:

{
  "message": "new-sec-token"
}

你需要将这个新的 message 值放入Cookie中,用于后续的请求。

cookies = {"X-BILI-SEC-TOKEN": message}

完整流程回顾

整个应对B站412风控的逆向流程可以总结为以下步骤:

  1. 请求触发:访问目标视频页面。
  2. 触发风控:收到412状态码响应。
  3. 提取令牌:从响应头的 Set-Cookie 中提取 X-BILI-SEC-TOKEN
  4. 解码参数:对令牌进行Base64解码,获取计算前缀 q 和目标哈希 r
  5. 暴力计算:在有限范围内寻找满足 sha256(q + i) == r 的整数 i
  6. 提交验证:将计算出的 i 和原始令牌提交至校验接口。
  7. 换取通行证:获取服务器返回的新令牌,并设置到Cookie中。
  8. 重新访问:携带新Cookie再次请求目标页面,即可成功获取内容。

这种风控机制设计巧妙,它通过增加自动化请求的计算成本,有效地过滤了简单的爬虫行为,同时又不至于对正常用户造成太大干扰。对于开发者而言,理解其原理不仅有助于解决具体的访问问题,也能更深入地思考如何设计健壮且友好的安全策略。对这类技术实战细节感兴趣的朋友,欢迎在云栈社区交流讨论。




上一篇:LightOnOCR-2-1B:10亿参数端到端OCR模型,精度与速度全面超越PaddleOCR与DeepSeek-OCR
下一篇:如何在Spring Boot应用中用JdbcClient集成SeekDB实现向量混合搜索
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-27 18:15 , Processed in 0.349480 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表