podflow 2025.1.26__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Podflow/__init__.py +137 -0
- Podflow/basic/__init__.py +2 -0
- Podflow/basic/file_save.py +21 -0
- Podflow/basic/folder_build.py +16 -0
- Podflow/basic/get_duration.py +18 -0
- Podflow/basic/get_file_list.py +57 -0
- Podflow/basic/get_html_dict.py +30 -0
- Podflow/basic/http_client.py +75 -0
- Podflow/basic/list_merge_tidy.py +15 -0
- Podflow/basic/qr_code.py +55 -0
- Podflow/basic/split_dict.py +14 -0
- Podflow/basic/time_format.py +16 -0
- Podflow/basic/time_stamp.py +61 -0
- Podflow/basic/vary_replace.py +11 -0
- Podflow/basic/write_log.py +43 -0
- Podflow/bilibili/__init__.py +2 -0
- Podflow/bilibili/build.py +201 -0
- Podflow/bilibili/get.py +477 -0
- Podflow/bilibili/login.py +307 -0
- Podflow/config/__init__.py +2 -0
- Podflow/config/build_original.py +41 -0
- Podflow/config/channge_icon.py +163 -0
- Podflow/config/correct_channelid.py +230 -0
- Podflow/config/correct_config.py +103 -0
- Podflow/config/get_channelid.py +22 -0
- Podflow/config/get_channelid_id.py +21 -0
- Podflow/config/get_config.py +34 -0
- Podflow/download/__init__.py +2 -0
- Podflow/download/convert_bytes.py +18 -0
- Podflow/download/delete_part.py +20 -0
- Podflow/download/dl_aideo_video.py +307 -0
- Podflow/download/show_progress.py +46 -0
- Podflow/download/wait_animation.py +34 -0
- Podflow/download/youtube_and_bilibili_download.py +30 -0
- Podflow/ffmpeg_judge.py +45 -0
- Podflow/httpfs/__init__.py +2 -0
- Podflow/httpfs/app_bottle.py +212 -0
- Podflow/httpfs/port_judge.py +21 -0
- Podflow/main.py +248 -0
- Podflow/makeup/__init__.py +2 -0
- Podflow/makeup/del_makeup_yt_format_fail.py +19 -0
- Podflow/makeup/make_up_file.py +51 -0
- Podflow/makeup/make_up_file_format_mod.py +96 -0
- Podflow/makeup/make_up_file_mod.py +30 -0
- Podflow/message/__init__.py +2 -0
- Podflow/message/backup_zip_save.py +45 -0
- Podflow/message/create_main_rss.py +44 -0
- Podflow/message/display_qrcode_and_url.py +36 -0
- Podflow/message/fail_message_initialize.py +165 -0
- Podflow/message/format_time.py +27 -0
- Podflow/message/get_original_rss.py +65 -0
- Podflow/message/get_video_format.py +111 -0
- Podflow/message/get_video_format_multithread.py +42 -0
- Podflow/message/get_youtube_and_bilibili_video_format.py +87 -0
- Podflow/message/media_format.py +195 -0
- Podflow/message/original_rss_fail_print.py +15 -0
- Podflow/message/rss_create_hash.py +26 -0
- Podflow/message/title_correction.py +30 -0
- Podflow/message/update_information_display.py +72 -0
- Podflow/message/update_youtube_bilibili_rss.py +116 -0
- Podflow/message/want_retry.py +21 -0
- Podflow/message/xml_item.py +83 -0
- Podflow/message/xml_original_item.py +92 -0
- Podflow/message/xml_rss.py +46 -0
- Podflow/netscape/__init__.py +2 -0
- Podflow/netscape/bulid_netscape.py +44 -0
- Podflow/netscape/get_cookie_dict.py +21 -0
- Podflow/parse_arguments.py +80 -0
- Podflow/remove/__init__.py +2 -0
- Podflow/remove/remove_dir.py +33 -0
- Podflow/remove/remove_file.py +23 -0
- Podflow/youtube/__init__.py +2 -0
- Podflow/youtube/build.py +287 -0
- Podflow/youtube/get.py +376 -0
- Podflow/youtube/login.py +39 -0
- podflow-2025.1.26.dist-info/METADATA +214 -0
- podflow-2025.1.26.dist-info/RECORD +80 -0
- podflow-2025.1.26.dist-info/WHEEL +5 -0
- podflow-2025.1.26.dist-info/entry_points.txt +6 -0
- podflow-2025.1.26.dist-info/top_level.txt +1 -0
@@ -0,0 +1,201 @@
|
|
1
|
+
# Podflow/bilibili/build.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import re
|
5
|
+
import html
|
6
|
+
import contextlib
|
7
|
+
from datetime import datetime, timezone
|
8
|
+
from Podflow import gVar
|
9
|
+
from Podflow.message.xml_rss import xml_rss
|
10
|
+
from Podflow.basic.file_save import file_save
|
11
|
+
from Podflow.message.xml_item import xml_item
|
12
|
+
from Podflow.bilibili.get import get_bilibili_cid
|
13
|
+
from Podflow.message.format_time import format_time
|
14
|
+
from Podflow.basic.get_file_list import get_file_list
|
15
|
+
from Podflow.message.xml_original_item import xml_original_item
|
16
|
+
|
17
|
+
|
18
|
+
def get_items_list(
|
19
|
+
guid,
|
20
|
+
item,
|
21
|
+
channelid_title,
|
22
|
+
title_change,
|
23
|
+
items_counts,
|
24
|
+
output_dir,
|
25
|
+
items_list,
|
26
|
+
):
|
27
|
+
pubDate = datetime.fromtimestamp(item["created"], timezone.utc).strftime(
|
28
|
+
"%Y-%m-%dT%H:%M:%S%z"
|
29
|
+
)
|
30
|
+
if guid in items_counts:
|
31
|
+
guid_parts = []
|
32
|
+
guid_edgeinfos = []
|
33
|
+
if "cid" in item:
|
34
|
+
pass
|
35
|
+
elif "part" in item:
|
36
|
+
guid_parts = item["part"]
|
37
|
+
elif "edgeinfo" in item:
|
38
|
+
guid_edgeinfos = item["edgeinfo"]
|
39
|
+
elif "error" in item:
|
40
|
+
pass # 需要添加错误处理
|
41
|
+
else:
|
42
|
+
guid_cid, guid_type, _ = get_bilibili_cid(
|
43
|
+
guid, gVar.channelid_bilibili_ids[output_dir]
|
44
|
+
)
|
45
|
+
if guid_type == "part":
|
46
|
+
guid_parts = guid_cid
|
47
|
+
elif guid_type == "edgeinfo":
|
48
|
+
guid_edgeinfos = guid_cid
|
49
|
+
if guid_parts and items_counts[guid] == len(guid_parts):
|
50
|
+
for guid_part in guid_parts:
|
51
|
+
guid_part_text = f"{item['title']} Part{guid_part['page']:0{len(str(len(guid_parts)))}}"
|
52
|
+
if item["title"] != guid_part["part"]:
|
53
|
+
guid_part_text += f" {guid_part['part']}"
|
54
|
+
xml_item_text = xml_item(
|
55
|
+
f"{item['bvid']}_p{guid_part['page']}",
|
56
|
+
output_dir,
|
57
|
+
f"https://www.bilibili.com/video/{guid}?p={guid_part['page']}",
|
58
|
+
channelid_title,
|
59
|
+
html.escape(guid_part_text),
|
60
|
+
html.escape(re.sub(r"\n+", "\n", item["description"])),
|
61
|
+
format_time(pubDate),
|
62
|
+
guid_part["first_frame"],
|
63
|
+
title_change,
|
64
|
+
)
|
65
|
+
items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
|
66
|
+
elif guid_edgeinfos and items_counts[guid] == len(guid_edgeinfos):
|
67
|
+
cid_edgeinfos = {
|
68
|
+
guid_edgeinfo["cid"]: guid_edgeinfo["title"]
|
69
|
+
for guid_edgeinfo in guid_edgeinfos
|
70
|
+
}
|
71
|
+
for guid_edgeinfo in guid_edgeinfos:
|
72
|
+
if guid_edgeinfo["options"]:
|
73
|
+
description = (
|
74
|
+
"〖互动视频〗\n"
|
75
|
+
+ "\n".join(
|
76
|
+
f"{option}\t✪{cid_edgeinfos[option_cid]}"
|
77
|
+
for option, option_cid in zip(
|
78
|
+
guid_edgeinfo["options"], guid_edgeinfo["options_cid"]
|
79
|
+
)
|
80
|
+
)
|
81
|
+
+ "\n------------------------------------------------\n"
|
82
|
+
+ item["description"]
|
83
|
+
)
|
84
|
+
else:
|
85
|
+
description = (
|
86
|
+
"〖互动视频〗\nTHE END."
|
87
|
+
+ "\n------------------------------------------------\n"
|
88
|
+
+ item["description"]
|
89
|
+
)
|
90
|
+
guid_edgeinfo_text = f"{item['title']} Part{guid_edgeinfo['num']:0{len(str(len(guid_edgeinfos)))}} {guid_edgeinfo['title']}"
|
91
|
+
xml_item_text = xml_item(
|
92
|
+
f"{item['bvid']}_{guid_edgeinfo['cid']}",
|
93
|
+
output_dir,
|
94
|
+
f"https://www.bilibili.com/video/{guid}",
|
95
|
+
channelid_title,
|
96
|
+
html.escape(guid_edgeinfo_text),
|
97
|
+
html.escape(re.sub(r"\n+", "\n", description)),
|
98
|
+
format_time(pubDate),
|
99
|
+
guid_edgeinfo["first_frame"],
|
100
|
+
title_change,
|
101
|
+
)
|
102
|
+
items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
|
103
|
+
else:
|
104
|
+
xml_item_text = xml_item(
|
105
|
+
item["bvid"],
|
106
|
+
output_dir,
|
107
|
+
f"https://www.bilibili.com/video/{guid}",
|
108
|
+
channelid_title,
|
109
|
+
html.escape(item["title"]),
|
110
|
+
html.escape(re.sub(r"\n+", "\n", item["description"])),
|
111
|
+
format_time(pubDate),
|
112
|
+
item["pic"],
|
113
|
+
title_change,
|
114
|
+
)
|
115
|
+
items_list.append(f"{xml_item_text}<!-- {output_dir} -->")
|
116
|
+
|
117
|
+
|
118
|
+
# 生成哔哩哔哩对应channel的需更新的items模块
|
119
|
+
def bilibili_xml_items(output_dir):
|
120
|
+
channelid_bilibili_value = gVar.channelid_bilibili[
|
121
|
+
gVar.channelid_bilibili_ids[output_dir]
|
122
|
+
]
|
123
|
+
content_id, items_counts = get_file_list(
|
124
|
+
output_dir, channelid_bilibili_value["media"]
|
125
|
+
)
|
126
|
+
items_list = [f"<!-- {output_dir} -->"]
|
127
|
+
entry_num = 0
|
128
|
+
original_judgment = True
|
129
|
+
channelid_title = channelid_bilibili_value["title"]
|
130
|
+
title_change = channelid_bilibili_value.get("title_change", [])
|
131
|
+
output_dir_value = gVar.channelid_bilibili_rss[output_dir]
|
132
|
+
# 最新更新
|
133
|
+
for guid in output_dir_value["content"]["list"]:
|
134
|
+
if guid not in gVar.video_id_failed and guid in content_id:
|
135
|
+
item = output_dir_value["content"]["entry"][guid]
|
136
|
+
get_items_list(
|
137
|
+
guid,
|
138
|
+
item,
|
139
|
+
channelid_title,
|
140
|
+
title_change,
|
141
|
+
items_counts,
|
142
|
+
output_dir,
|
143
|
+
items_list,
|
144
|
+
)
|
145
|
+
if item["description"] and item["description"][0] == "『":
|
146
|
+
original_judgment = False
|
147
|
+
entry_num += 1
|
148
|
+
if entry_num >= channelid_bilibili_value["update_size"]:
|
149
|
+
break
|
150
|
+
items_guid = re.findall(r"(?<=<guid>).+?(?=</guid>)", "".join(items_list))
|
151
|
+
# 存量接入
|
152
|
+
entry_count = channelid_bilibili_value["last_size"] - len(items_guid)
|
153
|
+
if gVar.xmls_original and output_dir in gVar.xmls_original and entry_count > 0:
|
154
|
+
xml_num = 0
|
155
|
+
for xml in gVar.xmls_original[output_dir].split(f"<!-- {output_dir} -->"):
|
156
|
+
xml_guid = re.search(r"(?<=<guid>).+(?=</guid>)", xml)
|
157
|
+
if (
|
158
|
+
xml_guid
|
159
|
+
and xml_guid.group() not in items_guid
|
160
|
+
and xml_guid.group() not in gVar.video_id_failed
|
161
|
+
):
|
162
|
+
items_list.append(
|
163
|
+
f"{xml_original_item(xml, channelid_title, original_judgment, title_change)}<!-- {output_dir} -->"
|
164
|
+
)
|
165
|
+
xml_num += 1
|
166
|
+
if xml_num >= entry_count:
|
167
|
+
break
|
168
|
+
# 向后更新
|
169
|
+
with contextlib.suppress(KeyError):
|
170
|
+
backward = output_dir_value["backward"]
|
171
|
+
for backward_guid in backward["list"]:
|
172
|
+
if (
|
173
|
+
backward_guid not in gVar.video_id_failed
|
174
|
+
and backward_guid in content_id
|
175
|
+
):
|
176
|
+
backward_item = backward["entry"][backward_guid]
|
177
|
+
get_items_list(
|
178
|
+
backward_guid,
|
179
|
+
backward_item,
|
180
|
+
channelid_title,
|
181
|
+
title_change,
|
182
|
+
items_counts,
|
183
|
+
output_dir,
|
184
|
+
items_list,
|
185
|
+
)
|
186
|
+
# 生成对应xml
|
187
|
+
description = html.escape(output_dir_value["content"]["sign"])
|
188
|
+
icon = output_dir_value["content"]["face"]
|
189
|
+
category = gVar.config["category"]
|
190
|
+
title = html.escape(output_dir_value["content"]["name"])
|
191
|
+
link = f"https://space.bilibili.com/{output_dir}"
|
192
|
+
items = "".join(items_list)
|
193
|
+
items = f"""<!-- {{{output_dir}}} -->
|
194
|
+
{items}
|
195
|
+
<!-- {{{output_dir}}} -->"""
|
196
|
+
file_save(
|
197
|
+
xml_rss(title, link, description, category, icon, items),
|
198
|
+
f"{output_dir}.xml",
|
199
|
+
"channel_rss",
|
200
|
+
)
|
201
|
+
return items
|
Podflow/bilibili/get.py
ADDED
@@ -0,0 +1,477 @@
|
|
1
|
+
# Podflow/bilibili/get.py
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
import contextlib
|
5
|
+
import re
|
6
|
+
import json
|
7
|
+
import math
|
8
|
+
import time
|
9
|
+
import urllib
|
10
|
+
import threading
|
11
|
+
from hashlib import md5
|
12
|
+
from functools import reduce
|
13
|
+
from Podflow import gVar
|
14
|
+
from Podflow.basic.http_client import http_client
|
15
|
+
from Podflow.basic.get_file_list import get_file_list
|
16
|
+
from Podflow.basic.list_merge_tidy import list_merge_tidy
|
17
|
+
|
18
|
+
|
19
|
+
# WBI签名模块
|
20
|
+
def WBI_signature(params={}, img_key="", sub_key=""):
|
21
|
+
mixinKeyEncTab = [
|
22
|
+
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
|
23
|
+
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
|
24
|
+
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
|
25
|
+
36, 20, 34, 44, 52,
|
26
|
+
]
|
27
|
+
|
28
|
+
def getMixinKey(orig: str):
|
29
|
+
"对 imgKey 和 subKey 进行字符顺序打乱编码"
|
30
|
+
return reduce(lambda s, i: s + orig[i], mixinKeyEncTab, "")[:32]
|
31
|
+
|
32
|
+
def encWbi(params: dict, img_key: str, sub_key: str):
|
33
|
+
"为请求参数进行 wbi 签名"
|
34
|
+
mixin_key = getMixinKey(img_key + sub_key)
|
35
|
+
curr_time = round(time.time())
|
36
|
+
params["wts"] = curr_time # 添加 wts 字段
|
37
|
+
params = dict(sorted(params.items())) # 按照 key 重排参数
|
38
|
+
# 过滤 value 中的 "!'()*" 字符
|
39
|
+
params = {
|
40
|
+
k: "".join(filter(lambda chr: chr not in "!'()*", str(v)))
|
41
|
+
for k, v in params.items()
|
42
|
+
}
|
43
|
+
query = urllib.parse.urlencode(params) # 序列化参数
|
44
|
+
wbi_sign = md5((query + mixin_key).encode()).hexdigest() # 计算 w_rid
|
45
|
+
params["w_rid"] = wbi_sign
|
46
|
+
return params
|
47
|
+
|
48
|
+
return encWbi(params=params, img_key=img_key, sub_key=sub_key)
|
49
|
+
|
50
|
+
|
51
|
+
# 获取bv的cid(包含分P或互动视频)模块
|
52
|
+
def get_bilibili_cid(bvid, bilibili_value):
|
53
|
+
bvid_part = [] # 用于存储每个分P或互动视频的信息
|
54
|
+
bvid_cid = [] # 存储已经获取的cid
|
55
|
+
bvid_cid_choices = [] # 存储互动视频的选择
|
56
|
+
code_num = {
|
57
|
+
0: "成功",
|
58
|
+
-400: "请求错误",
|
59
|
+
-403: "权限不足",
|
60
|
+
-404: "无视频",
|
61
|
+
62002: "稿件不可见",
|
62
|
+
62004: "稿件审核中",
|
63
|
+
62012: "仅UP主自己可见",
|
64
|
+
}
|
65
|
+
|
66
|
+
# 获取互动视频信息模块
|
67
|
+
def get_edge_info(bvid, bilibili_value, graph_version, edge_id):
|
68
|
+
if edgeinfo_v2_response := http_client(
|
69
|
+
"https://api.bilibili.com/x/stein/edgeinfo_v2",
|
70
|
+
f"{bilibili_value}|{bvid}",
|
71
|
+
10,
|
72
|
+
4,
|
73
|
+
True,
|
74
|
+
None,
|
75
|
+
{"bvid": bvid, "graph_version": graph_version, "edge_id": edge_id},
|
76
|
+
):
|
77
|
+
edgeinfo_v2 = edgeinfo_v2_response.json()
|
78
|
+
return edgeinfo_v2["data"]
|
79
|
+
|
80
|
+
# 获取选择项信息模块
|
81
|
+
def get_choices(data):
|
82
|
+
options = []
|
83
|
+
options_cid = []
|
84
|
+
if "questions" in data["edges"]:
|
85
|
+
for question in data["edges"]["questions"]:
|
86
|
+
if "choices" in question:
|
87
|
+
for choice in question["choices"]:
|
88
|
+
if (
|
89
|
+
choice["cid"] not in bvid_cid
|
90
|
+
and choice["cid"] not in bvid_cid_choices
|
91
|
+
):
|
92
|
+
bvid_cid_choices.append(
|
93
|
+
{
|
94
|
+
"cid": choice["cid"],
|
95
|
+
"edge_id": choice["id"],
|
96
|
+
"option": choice["option"],
|
97
|
+
}
|
98
|
+
)
|
99
|
+
options.append(choice["option"])
|
100
|
+
options_cid.append(choice["cid"])
|
101
|
+
return options, options_cid
|
102
|
+
|
103
|
+
# 获取剧情图id模块
|
104
|
+
def get_graph_version(bvid, bilibili_value, cid):
|
105
|
+
graph_version = ""
|
106
|
+
if playerwbi_response := http_client(
|
107
|
+
"https://api.bilibili.com/x/player/wbi/v2",
|
108
|
+
f"{bilibili_value}|{bvid}",
|
109
|
+
10,
|
110
|
+
4,
|
111
|
+
True,
|
112
|
+
None,
|
113
|
+
{"cid": cid, "bvid": bvid},
|
114
|
+
):
|
115
|
+
playerwbi = playerwbi_response.json()
|
116
|
+
playerwbi_data = playerwbi["data"]
|
117
|
+
if "interaction" in playerwbi_data:
|
118
|
+
graph_version = playerwbi["data"]["interaction"]["graph_version"]
|
119
|
+
return graph_version
|
120
|
+
|
121
|
+
# 判断媒体类型
|
122
|
+
if interface_response := http_client(
|
123
|
+
"https://api.bilibili.com/x/web-interface/wbi/view",
|
124
|
+
f"{bilibili_value}|{bvid}",
|
125
|
+
10,
|
126
|
+
4,
|
127
|
+
True,
|
128
|
+
gVar.bilibili_data["cookie"],
|
129
|
+
{"bvid": bvid},
|
130
|
+
):
|
131
|
+
interface_json = interface_response.json()
|
132
|
+
code = interface_json["code"]
|
133
|
+
if code != 0:
|
134
|
+
error = code_num[code]
|
135
|
+
return error, "error", None
|
136
|
+
data = interface_json["data"]
|
137
|
+
upower = data["is_upower_exclusive"]
|
138
|
+
pages = data["pages"]
|
139
|
+
cid = data["cid"]
|
140
|
+
if len(pages) > 1:
|
141
|
+
for part in pages:
|
142
|
+
bvid_part.append(
|
143
|
+
{
|
144
|
+
"cid": part["cid"],
|
145
|
+
"page": part["page"],
|
146
|
+
"part": part["part"],
|
147
|
+
"duration": part["duration"],
|
148
|
+
"dimension": part["dimension"],
|
149
|
+
"first_frame": part["first_frame"],
|
150
|
+
}
|
151
|
+
)
|
152
|
+
bvid_part.sort(key=lambda x: x["page"], reverse=True)
|
153
|
+
return bvid_part, "part", upower
|
154
|
+
elif data["rights"]["is_stein_gate"]:
|
155
|
+
# 获取互动视频信息
|
156
|
+
if graph_version := get_graph_version(bvid, bilibili_value, cid):
|
157
|
+
data_1 = get_edge_info(bvid, bilibili_value, graph_version, "1")
|
158
|
+
for story_list in data_1["story_list"]:
|
159
|
+
if story_list["edge_id"] == 1:
|
160
|
+
story_list_1 = story_list
|
161
|
+
break
|
162
|
+
options, options_cid = get_choices(data_1)
|
163
|
+
bvid_part.append(
|
164
|
+
{
|
165
|
+
"cid": story_list_1["cid"],
|
166
|
+
"title": data_1["title"],
|
167
|
+
"edge_id": story_list_1["edge_id"],
|
168
|
+
"first_frame": f"http://i0.hdslb.com/bfs/steins-gate/{story_list_1['cid']}_screenshot.jpg",
|
169
|
+
"options": options,
|
170
|
+
"options_cid": options_cid,
|
171
|
+
"num": 1,
|
172
|
+
}
|
173
|
+
)
|
174
|
+
bvid_cid.append(story_list_1["cid"])
|
175
|
+
while bvid_cid_choices:
|
176
|
+
if bvid_cid_choices[0]["cid"] not in bvid_cid:
|
177
|
+
data = get_edge_info(
|
178
|
+
bvid,
|
179
|
+
bilibili_value,
|
180
|
+
graph_version,
|
181
|
+
bvid_cid_choices[0]["edge_id"],
|
182
|
+
)
|
183
|
+
options, options_cid = get_choices(data)
|
184
|
+
bvid_part.append(
|
185
|
+
{
|
186
|
+
"cid": bvid_cid_choices[0]["cid"],
|
187
|
+
"title": data["title"],
|
188
|
+
"edge_id": bvid_cid_choices[0]["edge_id"],
|
189
|
+
"first_frame": f"http://i0.hdslb.com/bfs/steins-gate/{bvid_cid_choices[0]['cid']}_screenshot.jpg",
|
190
|
+
"options": options,
|
191
|
+
"options_cid": options_cid,
|
192
|
+
"num": len(bvid_part) + 1,
|
193
|
+
}
|
194
|
+
)
|
195
|
+
bvid_cid.append(bvid_cid_choices[0]["cid"])
|
196
|
+
del bvid_cid_choices[0]
|
197
|
+
bvid_part.sort(key=lambda x: x["num"], reverse=True)
|
198
|
+
return bvid_part, "edgeinfo", upower
|
199
|
+
else:
|
200
|
+
return None, None, None
|
201
|
+
else:
|
202
|
+
return cid, "cid", upower
|
203
|
+
else:
|
204
|
+
return None, None, None
|
205
|
+
|
206
|
+
|
207
|
+
# 查询哔哩哔哩用户投稿视频明细模块
|
208
|
+
def get_bilibili_vlist(bilibili_key, bilibili_value, num=1, all_part_judgement=False):
|
209
|
+
bilibili_list = []
|
210
|
+
bilibili_entry = {}
|
211
|
+
if bilibili_response := http_client(
|
212
|
+
"https://api.bilibili.com/x/space/wbi/arc/search",
|
213
|
+
bilibili_value,
|
214
|
+
10,
|
215
|
+
4,
|
216
|
+
True,
|
217
|
+
gVar.bilibili_data["cookie"],
|
218
|
+
WBI_signature(
|
219
|
+
{
|
220
|
+
"mid": bilibili_key,
|
221
|
+
"pn": str(num),
|
222
|
+
"ps": "25",
|
223
|
+
},
|
224
|
+
gVar.bilibili_data["img_key"],
|
225
|
+
gVar.bilibili_data["sub_key"],
|
226
|
+
),
|
227
|
+
):
|
228
|
+
bilibili_json = bilibili_response.json()
|
229
|
+
bilibili_vlists = bilibili_json["data"]["list"]["vlist"]
|
230
|
+
for vlist in bilibili_vlists:
|
231
|
+
with contextlib.suppress(KeyError, TypeError, IndexError, ValueError):
|
232
|
+
bilibili_entry[vlist["bvid"]] = {
|
233
|
+
"aid": vlist["aid"],
|
234
|
+
"author": vlist["author"],
|
235
|
+
"bvid": vlist["bvid"],
|
236
|
+
"copyright": vlist["copyright"],
|
237
|
+
"created": vlist["created"],
|
238
|
+
"description": vlist["description"],
|
239
|
+
"is_union_video": vlist["is_union_video"],
|
240
|
+
"length": vlist["length"],
|
241
|
+
"mid": vlist["mid"],
|
242
|
+
"pic": vlist["pic"],
|
243
|
+
"title": vlist["title"],
|
244
|
+
"typeid": vlist["typeid"],
|
245
|
+
}
|
246
|
+
bilibili_list.append(vlist["bvid"])
|
247
|
+
if all_part_judgement and bilibili_list:
|
248
|
+
|
249
|
+
def all_part(bvid):
|
250
|
+
bvid_cid, bvid_type, power = get_bilibili_cid(bvid, bilibili_value)
|
251
|
+
if bvid_type:
|
252
|
+
bilibili_entry[bvid][bvid_type] = bvid_cid
|
253
|
+
bilibili_entry[bvid]["power"] = power
|
254
|
+
|
255
|
+
# 创建一个线程列表
|
256
|
+
threads = []
|
257
|
+
for bvid in bilibili_list:
|
258
|
+
thread = threading.Thread(target=all_part, args=(bvid,))
|
259
|
+
threads.append(thread)
|
260
|
+
thread.start()
|
261
|
+
# 等待所有线程完成
|
262
|
+
for thread in threads:
|
263
|
+
thread.join()
|
264
|
+
return bilibili_entry, bilibili_list
|
265
|
+
|
266
|
+
|
267
|
+
# 更新哔哩哔哩频道json模块
|
268
|
+
def bilibili_json_update(bilibili_key, bilibili_value):
|
269
|
+
bilibili_space = {}
|
270
|
+
bilibili_lists = []
|
271
|
+
bilibili_entrys = {}
|
272
|
+
if not (
|
273
|
+
bilibili_card_response := http_client(
|
274
|
+
"https://api.bilibili.com/x/web-interface/card",
|
275
|
+
bilibili_value,
|
276
|
+
10,
|
277
|
+
4,
|
278
|
+
True,
|
279
|
+
gVar.bilibili_data["cookie"],
|
280
|
+
{
|
281
|
+
"mid": bilibili_key,
|
282
|
+
"photo": "true",
|
283
|
+
},
|
284
|
+
)
|
285
|
+
):
|
286
|
+
return None
|
287
|
+
bilibili_card_json = bilibili_card_response.json()
|
288
|
+
with contextlib.suppress(KeyError, TypeError, IndexError, ValueError):
|
289
|
+
if bilibili_card_json["code"] == 0:
|
290
|
+
bilibili_space = {
|
291
|
+
"mid": bilibili_card_json["data"]["card"]["mid"],
|
292
|
+
"name": bilibili_card_json["data"]["card"]["name"],
|
293
|
+
"sex": bilibili_card_json["data"]["card"]["sex"],
|
294
|
+
"face": bilibili_card_json["data"]["card"]["face"],
|
295
|
+
"spacesta": bilibili_card_json["data"]["card"]["spacesta"],
|
296
|
+
"sign": bilibili_card_json["data"]["card"]["sign"],
|
297
|
+
"Official": bilibili_card_json["data"]["card"]["Official"],
|
298
|
+
"official_verify": bilibili_card_json["data"]["card"][
|
299
|
+
"official_verify"
|
300
|
+
],
|
301
|
+
}
|
302
|
+
else:
|
303
|
+
return bilibili_card_json["code"]
|
304
|
+
# 查询哔哩哔哩用户投稿视频明细
|
305
|
+
for num in range(math.ceil(gVar.channelid_bilibili[bilibili_value]["update_size"] / 25)):
|
306
|
+
num += 1
|
307
|
+
bilibili_entry, bilibili_list = get_bilibili_vlist(
|
308
|
+
bilibili_key,
|
309
|
+
f"{bilibili_value}第{num}页",
|
310
|
+
num,
|
311
|
+
gVar.channelid_bilibili[bilibili_value]["AllPartGet"],
|
312
|
+
)
|
313
|
+
bilibili_entrys = bilibili_entrys | bilibili_entry
|
314
|
+
bilibili_lists += bilibili_list
|
315
|
+
bilibili_space["entry"] = bilibili_entrys
|
316
|
+
bilibili_space["list"] = bilibili_lists
|
317
|
+
return bilibili_space
|
318
|
+
|
319
|
+
|
320
|
+
# 更新哔哩哔哩频道xml模块
|
321
|
+
def bilibili_rss_update(bilibili_key, bilibili_value):
|
322
|
+
# 获取已下载文件列表
|
323
|
+
bilibili_content_bvid_original = get_file_list(
|
324
|
+
bilibili_key, gVar.channelid_bilibili[bilibili_value]["media"]
|
325
|
+
)[0]
|
326
|
+
# 获取原xml中文件列表
|
327
|
+
try:
|
328
|
+
original_item = gVar.xmls_original[bilibili_key] # 尝试获取原始的xml内容
|
329
|
+
guids = list_merge_tidy(
|
330
|
+
re.findall(r"(?<=<guid>).+(?=</guid>)", original_item), [], 12
|
331
|
+
) # 从xml中提取guid
|
332
|
+
except KeyError:
|
333
|
+
guids = [] # 如果没有找到对应的key,则初始化guids为空列表
|
334
|
+
bilibili_space = bilibili_json_update(
|
335
|
+
bilibili_key, bilibili_value
|
336
|
+
) # 更新bilibili相关的json内容
|
337
|
+
# 读取原哔哩哔哩频道xml文件并判断是否要更新
|
338
|
+
try:
|
339
|
+
with open(
|
340
|
+
f"channel_id/{bilibili_key}.json",
|
341
|
+
"r",
|
342
|
+
encoding="utf-8", # 打开指定的json文件
|
343
|
+
) as file:
|
344
|
+
bilibili_space_original = json.load(file) # 读取文件内容并解析成字典
|
345
|
+
except FileNotFoundError: # 捕获文件不存在异常
|
346
|
+
bilibili_space_original = {} # 如果文件不存在,初始化为空字典
|
347
|
+
except json.decoder.JSONDecodeError: # 捕获json解码错误
|
348
|
+
bilibili_space_original = {} # 如果json读取失败,初始化为空字典
|
349
|
+
# 根据更新条件更新频道数据
|
350
|
+
if bilibili_space == -404: # 检查更新状态
|
351
|
+
gVar.channelid_bilibili_rss[bilibili_key] = {
|
352
|
+
"content": bilibili_space,
|
353
|
+
"type": "int",
|
354
|
+
} # 设置为整型内容
|
355
|
+
elif bilibili_space is None:
|
356
|
+
gVar.channelid_bilibili_rss[bilibili_key] = {
|
357
|
+
"content": bilibili_space_original,
|
358
|
+
"type": "json",
|
359
|
+
} # 使用原始json内容
|
360
|
+
else:
|
361
|
+
gVar.channelid_bilibili_rss[bilibili_key] = {
|
362
|
+
"content": bilibili_space,
|
363
|
+
"type": "dict",
|
364
|
+
} # 设置为字典类型内容
|
365
|
+
# 判断是否需要更新ID列表
|
366
|
+
if bilibili_space != bilibili_space_original:
|
367
|
+
gVar.channelid_bilibili_ids_update[bilibili_key] = bilibili_value # 更新ID
|
368
|
+
# 获取需要更新的内容列表
|
369
|
+
bilibili_content_bvid = bilibili_space["list"][
|
370
|
+
: gVar.channelid_bilibili[bilibili_value]["update_size"]
|
371
|
+
]
|
372
|
+
bilibili_space_new = list_merge_tidy(
|
373
|
+
bilibili_content_bvid, guids
|
374
|
+
) # 合并新内容和原内容
|
375
|
+
# 检查内容是否有变动
|
376
|
+
if bilibili_content_bvid := [
|
377
|
+
exclude
|
378
|
+
for exclude in bilibili_content_bvid
|
379
|
+
if exclude not in bilibili_content_bvid_original # 筛选新增的内容
|
380
|
+
]:
|
381
|
+
gVar.channelid_bilibili_ids_update[bilibili_key] = bilibili_value # 需要更新ID
|
382
|
+
gVar.bilibili_content_bvid_update[bilibili_key] = (
|
383
|
+
bilibili_content_bvid # 更新新增内容
|
384
|
+
)
|
385
|
+
# 向后更新
|
386
|
+
if (
|
387
|
+
gVar.channelid_bilibili[bilibili_value]["BackwardUpdate"] and guids
|
388
|
+
): # 如果设置了向后更新
|
389
|
+
backward_update_size = gVar.channelid_bilibili[bilibili_value][
|
390
|
+
"last_size"
|
391
|
+
] - len(bilibili_space_new) # 计算需要向后更新的数量
|
392
|
+
if backward_update_size > 0:
|
393
|
+
backward_update_size = min(
|
394
|
+
backward_update_size,
|
395
|
+
gVar.channelid_bilibili[bilibili_value]["BackwardUpdate_size"],
|
396
|
+
) # 限制更新数量
|
397
|
+
backward_update_page_start = math.ceil(
|
398
|
+
len(bilibili_space_new) / 25
|
399
|
+
) # 确定开始页面
|
400
|
+
backward_update_page_end = math.ceil(
|
401
|
+
(len(bilibili_space_new) + backward_update_size) / 25
|
402
|
+
) # 确定结束页面
|
403
|
+
backward_entry = {} # 初始化向后更新的条目
|
404
|
+
backward_list = [] # 初始化向后更新的列表
|
405
|
+
# 循环更新每一页的内容
|
406
|
+
for num in range(
|
407
|
+
backward_update_page_start, backward_update_page_end + 1
|
408
|
+
):
|
409
|
+
backward_entry_part, backward_list_part = get_bilibili_vlist(
|
410
|
+
bilibili_key, bilibili_value, num
|
411
|
+
) # 获取具体内容
|
412
|
+
backward_entry = backward_entry | backward_entry_part # 合并条目
|
413
|
+
backward_list += backward_list_part # 合并列表
|
414
|
+
# 检查条目和列表是否有效
|
415
|
+
if backward_entry and backward_list and guids[-1] in backward_list:
|
416
|
+
try:
|
417
|
+
backward_list_start = (
|
418
|
+
backward_list.index(guids[-1]) + 1
|
419
|
+
) # 获取guids的起始索引
|
420
|
+
backward_list = backward_list[backward_list_start:][
|
421
|
+
:backward_update_size
|
422
|
+
] # 更新向后列表
|
423
|
+
except ValueError:
|
424
|
+
backward_list = [] # 如果没有找到,清空列表
|
425
|
+
# 根据条件移除已经存在的元素
|
426
|
+
for guid in backward_list.copy():
|
427
|
+
if guid in bilibili_space_new:
|
428
|
+
backward_list.remove(guid) # 移除已存在的条目
|
429
|
+
# 如果有向后条目需要更新
|
430
|
+
if backward_list:
|
431
|
+
if gVar.channelid_bilibili[bilibili_value][
|
432
|
+
"AllPartGet"
|
433
|
+
]: # 如果需要获取所有部分
|
434
|
+
|
435
|
+
def backward_all_part(guid):
|
436
|
+
guid_cid, guid_type, power = get_bilibili_cid(
|
437
|
+
guid, bilibili_value
|
438
|
+
)
|
439
|
+
if guid_type:
|
440
|
+
backward_entry[guid][guid_type] = guid_cid
|
441
|
+
backward_entry[guid]["power"] = power
|
442
|
+
|
443
|
+
# 创建一个线程列表
|
444
|
+
threads = []
|
445
|
+
for guid in backward_list:
|
446
|
+
thread = threading.Thread(
|
447
|
+
target=backward_all_part, args=(guid,)
|
448
|
+
) # 为每个条目创建线程
|
449
|
+
threads.append(thread) # 添加线程到列表
|
450
|
+
thread.start() # 启动线程
|
451
|
+
# 等待所有线程完成
|
452
|
+
for thread in threads:
|
453
|
+
thread.join()
|
454
|
+
# 更新频道信息
|
455
|
+
gVar.channelid_bilibili_rss[bilibili_key].update(
|
456
|
+
{
|
457
|
+
"backward": {
|
458
|
+
"list": backward_list,
|
459
|
+
"entry": backward_entry,
|
460
|
+
}
|
461
|
+
}
|
462
|
+
)
|
463
|
+
gVar.channelid_bilibili_ids_update[bilibili_key] = (
|
464
|
+
bilibili_value # 标记ID更新
|
465
|
+
)
|
466
|
+
bilibili_content_bvid_backward = [] # 初始化向后更新的内容列表
|
467
|
+
for guid in backward_list:
|
468
|
+
if (
|
469
|
+
guid not in bilibili_content_bvid_original
|
470
|
+
): # 检查新增的内容
|
471
|
+
bilibili_content_bvid_backward.append(
|
472
|
+
guid
|
473
|
+
) # 添加到向后更新列表
|
474
|
+
if bilibili_content_bvid_backward:
|
475
|
+
gVar.bilibili_content_bvid_backward_update[bilibili_key] = (
|
476
|
+
bilibili_content_bvid_backward # 更新最终的向后更新内容
|
477
|
+
)
|