Files
2026-03-21_why-manifest/archive_scripts/temp_sort.py

218 lines
7.5 KiB
Python
Executable File
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 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)