HeXi/hexi/plugins/fuck_pilipili/sign.py
sansenhoshi 275f05ee4a 重构
2026-01-04 17:15:40 +08:00

114 lines
3.5 KiB
Python
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.

import hmac
import hashlib
import time
import urllib.parse
from functools import reduce
from hashlib import md5
from aiohttp import ClientSession
# doc: https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/wbi.md
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
}
# fmt: off
mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52
]
# fmt: on
def getMixinKey(orig: str):
"对 imgKey 和 subKey 进行字符顺序打乱编码"
return reduce(lambda s, i: s + orig[i], mixinKeyEncTab, "")[:32]
def encWbi(params: dict, img_key: str, sub_key: str):
"为请求参数进行 wbi 签名"
mixin_key = getMixinKey(img_key + sub_key)
curr_time = round(time.time())
params["wts"] = curr_time # 添加 wts 字段
params = dict(sorted(params.items())) # 按照 key 重排参数
# 过滤 value 中的 "!'()*" 字符
params = {
k: "".join(filter(lambda chr: chr not in "!'()*", str(v)))
for k, v in params.items()
}
query = urllib.parse.urlencode(params) # 序列化参数
wbi_sign = md5((query + mixin_key).encode()).hexdigest() # 计算 w_rid
params["w_rid"] = wbi_sign
return params
async def getWbiKeys():
"获取最新的 img_key 和 sub_key"
async with ClientSession(headers=headers) as session:
async with session.get("https://api.bilibili.com/x/web-interface/nav") as resp:
json_content = await resp.json()
img_url: str = json_content["data"]["wbi_img"]["img_url"]
sub_url: str = json_content["data"]["wbi_img"]["sub_url"]
img_key = img_url.rsplit("/", 1)[1].split(".")[0]
sub_key = sub_url.rsplit("/", 1)[1].split(".")[0]
return img_key, sub_key
async def get_query(params: dict):
"""
获取签名后的查询参数
"""
img_key, sub_key = await getWbiKeys()
signed_params = encWbi(params=params, img_key=img_key, sub_key=sub_key)
query = urllib.parse.urlencode(signed_params)
return query
def hmac_sha256(key, message):
"""
使用HMAC-SHA256算法对给定的消息进行加密
:param key: 密钥
:param message: 要加密的消息
:return: 加密后的哈希值
"""
# 将密钥和消息转换为字节串
key = key.encode("utf-8")
message = message.encode("utf-8")
# 创建HMAC对象使用SHA256哈希算法
hmac_obj = hmac.new(key, message, hashlib.sha256)
# 计算哈希值
hash_value = hmac_obj.digest()
# 将哈希值转换为十六进制字符串
hash_hex = hash_value.hex()
return hash_hex
async def get_ticket():
"""
获取ticket
"""
o = hmac_sha256("XgwSnGZ1p", f"ts{int(time.time())}")
url = "https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket"
params = {
"key_id": "ec02",
"hexsign": o,
"context[ts]": f"{int(time.time())}",
"csrf": "",
}
async with ClientSession(headers=headers) as session:
async with session.post(url, params=params) as resp:
json_content = await resp.json()
return json_content["data"]["ticket"]
if __name__ == "__main__":
import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete(get_ticket())