Initial commit: sanitize repository for remote push
This commit is contained in:
218
archive_scripts/temp_sort.py
Executable file
218
archive_scripts/temp_sort.py
Executable file
@ -0,0 +1,218 @@
|
||||
import requests
|
||||
import time
|
||||
import json
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
# ================= 配置区域 =================
|
||||
COOKIE_FILE = Path("./cookies.json")
|
||||
TARGET_SEASON_ID = 7196643 # 目标合集 ID
|
||||
ASCENDING_ORDER = True # True: 最早发布的在前面 (1, 2, 3...)
|
||||
# ===========================================
|
||||
|
||||
def extract_cookie_from_list(cookie_list):
|
||||
"""从列表结构中提取 SESSDATA 和 bili_jct"""
|
||||
sessdata = ""
|
||||
bili_jct = ""
|
||||
for item in cookie_list:
|
||||
if item.get("name") == "SESSDATA":
|
||||
sessdata = item.get("value")
|
||||
elif item.get("name") == "bili_jct":
|
||||
bili_jct = item.get("value")
|
||||
return sessdata, bili_jct
|
||||
|
||||
def load_cookies(file_path):
|
||||
"""智能从 json 文件加载 cookies"""
|
||||
if not file_path.exists():
|
||||
print(f"[!] 错误: 找不到文件 {file_path}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
sessdata = ""
|
||||
bili_jct = ""
|
||||
|
||||
if isinstance(data, list):
|
||||
sessdata, bili_jct = extract_cookie_from_list(data)
|
||||
elif isinstance(data, dict):
|
||||
if "cookie_info" in data and "cookies" in data["cookie_info"]:
|
||||
sessdata, bili_jct = extract_cookie_from_list(data["cookie_info"]["cookies"])
|
||||
elif "cookies" in data and isinstance(data["cookies"], list):
|
||||
sessdata, bili_jct = extract_cookie_from_list(data["cookies"])
|
||||
else:
|
||||
sessdata = data.get("SESSDATA", "")
|
||||
bili_jct = data.get("bili_jct", "")
|
||||
|
||||
if not sessdata or not bili_jct:
|
||||
print("[!] 错误: cookies.json 中未找到 SESSDATA 或 bili_jct")
|
||||
exit(1)
|
||||
|
||||
return sessdata, bili_jct
|
||||
except Exception as e:
|
||||
print(f"[!] 解析 cookies.json 失败: {e}")
|
||||
exit(1)
|
||||
|
||||
# 初始化 Cookie
|
||||
SESSDATA, BILI_JCT = load_cookies(COOKIE_FILE)
|
||||
|
||||
print(f"[*] SESSDATA 读取成功: {SESSDATA[:4]}...{SESSDATA[-4:]}")
|
||||
print(f"[*] bili_jct 读取成功: {BILI_JCT[:4]}...{BILI_JCT[-4:]}")
|
||||
|
||||
HEADERS = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
||||
"Cookie": f"SESSDATA={SESSDATA}; bili_jct={BILI_JCT}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def get_section_id_by_season(season_id):
|
||||
"""查找合集对应的小节ID"""
|
||||
print(f"[*] 正在查找合集 ID {season_id} 的小节信息...")
|
||||
url = "https://member.bilibili.com/x2/creative/web/seasons"
|
||||
|
||||
page = 1
|
||||
while True:
|
||||
params = {"pn": page, "ps": 30, "order": "", "sort": ""}
|
||||
resp = requests.get(url, params=params, headers=HEADERS)
|
||||
data = resp.json()
|
||||
|
||||
if data["code"] != 0:
|
||||
print(f"[!] 获取合集列表失败: {data['message']}")
|
||||
if data["code"] == -101:
|
||||
print("[!] 提示: 账号未登录,请检查 cookies.json")
|
||||
return None
|
||||
|
||||
seasons_list = data["data"]["seasons"]
|
||||
if not seasons_list:
|
||||
break
|
||||
|
||||
for s_obj in seasons_list:
|
||||
s_info = s_obj["season"]
|
||||
if s_info["id"] == season_id:
|
||||
title = s_info["title"]
|
||||
print(f"[*] 找到合集: 《{title}》")
|
||||
|
||||
if "sections" in s_obj and "sections" in s_obj["sections"]:
|
||||
first_section = s_obj["sections"]["sections"][0]
|
||||
sec_id = first_section["id"]
|
||||
sec_title = first_section["title"]
|
||||
print(f"[*] 锁定小节: [{sec_title}] (Section ID: {sec_id})")
|
||||
return sec_id
|
||||
else:
|
||||
print("[!] 该合集下没有发现小节结构。")
|
||||
return None
|
||||
|
||||
page += 1
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"[!] 未在您的账号中找到 Season ID: {season_id}")
|
||||
return None
|
||||
|
||||
def get_video_publish_time(bvid):
|
||||
"""
|
||||
获取视频发布时间
|
||||
[FIXED] 增加了 headers 参数,防止 B 站拦截请求
|
||||
"""
|
||||
url = "https://api.bilibili.com/x/web-interface/view"
|
||||
params = {"bvid": bvid}
|
||||
try:
|
||||
# !!!关键修改:这里必须带上 headers !!!
|
||||
resp = requests.get(url, params=params, headers=HEADERS)
|
||||
data = resp.json()
|
||||
|
||||
if data["code"] == 0:
|
||||
return data["data"]["pubdate"], data["data"]["title"]
|
||||
else:
|
||||
# 打印具体错误原因
|
||||
print(f"\n[!] 获取视频 {bvid} 失败: code={data['code']}, msg={data['message']}")
|
||||
return 0, "Unknown"
|
||||
except Exception as e:
|
||||
print(f"\n[!] 请求异常: {e}")
|
||||
return 0, "Unknown"
|
||||
|
||||
def sort_videos(section_id):
|
||||
# 1. 获取小节内视频
|
||||
url_get = "https://member.bilibili.com/x2/creative/web/season/section"
|
||||
resp = requests.get(url_get, params={"id": section_id}, headers=HEADERS)
|
||||
res_json = resp.json()
|
||||
|
||||
if res_json["code"] != 0:
|
||||
print(f"[!] API 错误: {res_json['message']}")
|
||||
return
|
||||
|
||||
section_info = res_json["data"]["section"]
|
||||
episodes = res_json["data"]["episodes"]
|
||||
|
||||
if not episodes:
|
||||
print("[!] 合集内无视频。")
|
||||
return
|
||||
|
||||
total = len(episodes)
|
||||
print(f"[*] 获取到 {total} 个视频,开始查询发布时间...")
|
||||
|
||||
video_list = []
|
||||
success_count = 0
|
||||
|
||||
for idx, ep in enumerate(episodes):
|
||||
# 随机延迟 0.2 ~ 0.5 秒,比固定延迟更安全
|
||||
time.sleep(random.uniform(0.2, 0.5))
|
||||
|
||||
bvid = ep["bvid"]
|
||||
pubdate, title = get_video_publish_time(bvid)
|
||||
|
||||
# 简单的进度显示
|
||||
date_str = "Fail/Unknown"
|
||||
if pubdate != 0:
|
||||
date_str = time.strftime('%Y-%m-%d', time.localtime(pubdate))
|
||||
success_count += 1
|
||||
|
||||
print(f" [{idx+1}/{total}] {title[:15]:<15} -> {date_str}")
|
||||
|
||||
video_list.append({
|
||||
"id": ep["id"],
|
||||
"title": ep["title"] if title == "Unknown" else title, # 优先使用 API 查到的全名
|
||||
"pubdate": pubdate
|
||||
})
|
||||
|
||||
if success_count == 0:
|
||||
print("[!] 错误: 所有视频时间查询均失败,终止排序以免数据混乱。")
|
||||
return
|
||||
|
||||
# 2. 排序
|
||||
print("[*] 正在计算排序顺序...")
|
||||
video_list.sort(key=lambda x: x['pubdate'], reverse=not ASCENDING_ORDER)
|
||||
|
||||
# 3. 提交
|
||||
print("[*] 正在提交新的排序列表...")
|
||||
sorts_payload = [{"id": v["id"], "sort": i+1} for i, v in enumerate(video_list)]
|
||||
|
||||
payload = {
|
||||
"section": {
|
||||
"id": section_info["id"],
|
||||
"seasonId": section_info["seasonId"],
|
||||
"title": section_info["title"],
|
||||
"type": section_info["type"]
|
||||
},
|
||||
"sorts": sorts_payload
|
||||
}
|
||||
|
||||
url_edit = f"https://member.bilibili.com/x2/creative/web/season/section/edit?csrf={BILI_JCT}"
|
||||
try:
|
||||
resp_submit = requests.post(url_edit, json=payload, headers=HEADERS)
|
||||
result = resp_submit.json()
|
||||
|
||||
if result["code"] == 0:
|
||||
print(f"\n[SUCCESS] 合集《{section_info['title']}》排序更新成功!")
|
||||
else:
|
||||
print(f"\n[FAIL] 更新失败: {result['message']}")
|
||||
except Exception as e:
|
||||
print(f"\n[!] 提交时发生网络错误: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("--- Bilibili 合集自动排序工具 (v2.0 fixed) ---")
|
||||
|
||||
target_section_id = get_section_id_by_season(TARGET_SEASON_ID)
|
||||
|
||||
if target_section_id:
|
||||
sort_videos(target_section_id)
|
||||
Reference in New Issue
Block a user