Last active
November 10, 2021 11:51
-
-
Save zhongfly/c6b419312da5fafc9afdf809b257137b to your computer and use it in GitHub Desktop.
B站国际版简中字幕下载
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- encoding: utf-8 -*- | |
# python3.6 | |
import json | |
import os | |
import requests | |
th_api = "https://api.biliintl.com" | |
BangumiInfoUrl = th_api + "/intl/gateway/web/view/ogv_collection" | |
SubInfoUrl = th_api + "/intl/gateway/v2/app/subtitle" | |
th_api_proxy = "https://api.global.bilibili.com" # 可用漫游代理https://github.com/yujincheng08/BiliRoaming/wiki/ | |
BangumiInfoUrl_proxy = th_api_proxy + "/intl/gateway/v2/ogv/view/app/season" | |
def download(url, path): | |
r = requests.get(url, stream=True) | |
r.raise_for_status() | |
f = open(path, "wb") | |
for chunk in r.iter_content(chunk_size=1024): | |
if chunk: | |
f.write(chunk) | |
f.close() | |
def getBangumiInfo(season_id): | |
r = requests.get( | |
BangumiInfoUrl, | |
params={"season_id": int(season_id), "s_locale": "zh_Hans"}, | |
).json() | |
if r["code"] == 0: | |
return r["data"]["episodes"] | |
else: | |
raise Exception(f'Warn: getBangumiInfo for {season_id} message:{r["message"]}') | |
def getSubUrl(ep_id): | |
r = requests.get( | |
SubInfoUrl, | |
params={"ep_id": int(ep_id), "s_locale": "zh_Hans"}, | |
).json() | |
if r["code"] == 0: | |
if r["data"]["suggest_key"] == "zh-Hans": | |
return r["data"]["subtitles"][0]["url"] | |
else: | |
raise Exception(f"Warn: getSubUrl for {ep_id} message:无中文简体字幕") | |
else: | |
raise Exception(f'Warn: getSubUrl for {ep_id} message:{r["message"]}') | |
def printBangumiInfo(episodesData): | |
for (ord, episode) in enumerate(episodesData, start=1): | |
print( | |
f"{ord:<3} 剧集id:{episode['ep_id']},剧集名:{episode['title']} {episode['long_title']}" | |
) | |
def downloadSub(season_id): | |
episodesData = getBangumiInfo(season_id=season_id) | |
printBangumiInfo(episodesData) | |
ep_ord = int(input("请输入需要下载的剧集对应的序号:")) - 1 | |
ep = episodesData[ep_ord] | |
url = getSubUrl(ep["ep_id"]) | |
path = f"{ep['title']} {ep['long_title']}.json" | |
download(url, path) | |
return path | |
def getBangumiInfo_proxy(season_id): | |
r = requests.get( | |
BangumiInfoUrl_proxy, | |
params={ | |
"area": "th", | |
"s_locale": "zh_SG", | |
"access_key": "2021", | |
"season_id": season_id, | |
"mobi_app": "bstar_a", | |
"build": "1080003", | |
}, | |
headers={"http_x_from_biliroaming": "*"}, | |
) | |
result = r.json() | |
if result["code"] == 0: | |
return result["result"]["modules"][0]["data"]["episodes"] | |
else: | |
raise Exception( | |
f'Warn: getSubUrl_proxy for {season_id} message:{result["message"]}' | |
) | |
def printBangumiInfo_proxy(episodesData): | |
for (ord, episode) in enumerate(episodesData, start=1): | |
sub_keys = "" | |
for sub in episode["subtitles"]: | |
sub_keys +=f"{sub['key']} " | |
print(f"{ord:<3} 剧集id:{episode['id']},剧集名:{episode['long_title_display']},语言:{sub_keys.rstrip()}") | |
def downloadSub_proxy(season_id): | |
episodesData = getBangumiInfo_proxy(season_id) | |
printBangumiInfo_proxy(episodesData) | |
ep_ord = int(input("请输入需要下载的剧集对应的序号:")) - 1 | |
ep = episodesData[ep_ord] | |
for sub in ep["subtitles"]: | |
if sub["key"] == "zh-Hans": | |
url = sub["url"] | |
path = f"{ep['long_title_display']}.json" | |
download(url, path) | |
return path | |
sub_keys = "" | |
for sub in ep["subtitles"]: | |
sub_keys +=f"{sub['key']} " | |
print(f"Warn: downloadSub_proxy for {season_id} message:无中文简体字幕,有以下语言:{sub_keys.rstrip()}") | |
# 以下代码来自https://github.com/y2361547758/bcc2ass/blob/master/bcc2ass.py | |
def sec2time(sec, type=""): | |
h = int(sec) // 3600 | |
m = int(sec) // 60 % 60 | |
s = sec % 60 | |
f = int(sec * 1000) % 1000 | |
if type == "srt": | |
return "%02d:%02d:%02d,%03d" % (h, m, int(s), f) | |
elif type == "ass": | |
return "%d:%02d:%02d.%02d" % (h, m, s, f // 10) | |
elif type == "lrc": | |
return "%02d:%02d.%02d" % (int(sec) // 60, s, f // 10) | |
return "%02d:%02d:%02.2f" % (h, m, s) | |
def color2asscolor(color, alpha=0): | |
return ("&H%02X" % alpha) + color[1:] | |
def bcc2ass(bcc_file, type): | |
font_size_ratio = 50 | |
with open(bcc_file, encoding="utf-8") as f: | |
bcc = json.load(f) | |
output = f"{os.path.splitext(bcc_file)[0]}.{type}" | |
with open(output, "w", encoding="utf-8") as f: | |
count = 1 | |
if type == "ass": | |
print("[V4+ Styles]", file=f) | |
print( | |
"Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", | |
file=f, | |
) | |
location = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0} | |
Alignment = 2 | |
for i in bcc["body"]: | |
location[i["location"]] += 1 | |
if location[Alignment] < location[i["location"]]: | |
Alignment = i["location"] | |
print( | |
"Style: Default", | |
"Arial", | |
"%d" % (bcc["font_size"] * font_size_ratio), | |
color2asscolor(bcc["font_color"]), | |
"&H000000FF", | |
color2asscolor( | |
bcc["background_color"], int(bcc["background_alpha"] * 0xFF) | |
), | |
"&H00000000,0,0,0,0,100,100,0,0,1,2,2,%d,10,10,10,1" % Alignment, | |
sep=",", | |
file=f, | |
) | |
print(file=f) | |
print("[Events]", file=f) | |
print( | |
"Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text", | |
file=f, | |
) | |
for i in bcc["body"]: | |
if type == "srt": | |
print(count, file=f) | |
print( | |
sec2time(i["from"], type) + " --> " + sec2time(i["to"], type), | |
file=f, | |
) | |
print(i["content"], file=f) | |
print(file=f) | |
count += 1 | |
elif type == "ass": | |
align = "" if i["location"] == Alignment else "{\\a%d}" % i["location"] | |
print( | |
"Dialogue: 0," | |
+ sec2time(i["from"], type) | |
+ "," | |
+ sec2time(i["to"], type) | |
+ ",Default,,0,0,0,," | |
+ align | |
+ i["content"].replace("\n", r"\N"), | |
file=f, | |
) | |
if __name__ == "__main__": | |
while True: | |
try: | |
# season_id = 1010919 | |
season_id = int(input("请输入番剧season_id:")) | |
# bcc_file = downloadSub(season_id) | |
bcc_file = downloadSub_proxy(season_id) | |
bcc2ass(bcc_file, "srt") | |
except Exception as e: | |
print(e) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment