Skip to content

Commit eb81e4a

Browse files
committed
feat: improve fetch_lesson_list
Signed-off-by: 晨叶梦春 <wuziqian211@126.com>
1 parent 7bbc40e commit eb81e4a

File tree

1 file changed

+45
-39
lines changed

1 file changed

+45
-39
lines changed

src/tchMaterial-parser.pyw

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,13 @@ def parse(url: str, bookmarks: bool) -> tuple[str, str, list] | tuple[None, None
201201
"title": f"第 {i+1} 节 (P{m['page_number']})",
202202
"page_index": m["page_number"]
203203
})
204+
204205
except Exception as e:
205206
print_error(e)
206207
chapters = []
207208

208209
return resource_url, title, chapters
210+
209211
except Exception as e:
210212
print_error(e)
211213
return None, None, None
@@ -283,9 +285,9 @@ def download_file(url: str, save_path: str, chapters: list | None = None) -> Non
283285
current_state["total_size"] = int(response.headers.get("Content-Length", 0))
284286

285287
with open(save_path, "wb") as file:
286-
for chunk in response.iter_content(
288+
for chunk in response.iter_content( # 分块下载
287289
chunk_size=131072 if current_state["total_size"] < 20971520 else 262144 if current_state["total_size"] < 52428800 else 524288
288-
): # 分块下载
290+
):
289291
file.write(chunk)
290292
current_state["downloaded_size"] += len(chunk)
291293
all_downloaded_size = sum(state["downloaded_size"] for state in download_states)
@@ -299,9 +301,11 @@ def download_file(url: str, save_path: str, chapters: list | None = None) -> Non
299301
ui_call(progress_label.config, text=f"{format_bytes(all_downloaded_size)}/{format_bytes(all_total_size)} ({download_progress:.2f}%) 已下载 {downloaded_number}/{total_number}") # 更新标签以显示当前下载进度
300302

301303
current_state["downloaded_size"] = current_state["total_size"]
302-
if chapters:
304+
305+
if chapters: # 添加书签
303306
ui_call(progress_label.config, text="添加书签")
304307
add_bookmarks(save_path, chapters)
308+
305309
current_state["finished"] = True
306310

307311
except Exception as e:
@@ -344,37 +348,32 @@ def add_bookmarks(pdf_path: str, chapters: list) -> None: # 给 PDF 添加书签
344348
writer = PdfWriter()
345349
writer.append_pages_from_reader(reader)
346350

347-
# 递归添加书签的内部函数
348-
def _add_chapter(chapter_list, parent=None):
351+
def add_chapter(chapter_list, parent=None): # 递归添加书签的内部函数
349352
for chapter in chapter_list:
350353
title = chapter.get("title", "未知章节")
351-
# 1. 获取原始值
352354
p_index = chapter.get("page_index")
353-
# 2. 如果值为 None (JSON里的null) 或者不存在,跳过这个书签(因为未使用)
354-
if p_index is None:
355+
if p_index is None: # 如果值为 None 或者不存在,跳过这个书签
355356
print_error(ValueError(f"章节 “{title}” 的页码索引无效,已跳过此处书签添加"))
356357
continue
357-
# 3. 尝试将其转为整数并减 1 (pypdf 页码从 0 开始)
358-
try:
358+
359+
try: # 尝试将其转为整数并减 1(pypdf 页码从 0 开始)
359360
page_num = int(p_index) - 1
360-
except (ValueError, TypeError):
361-
page_num = 0 # 如果转换失败,默认指向第1页
362-
# page_num = chapter.get("page_index", 1) - 1
363-
if page_num < 0: page_num = 0
361+
except (ValueError, TypeError) as e: # 如果转换失败,跳过这个书签
362+
print_error(e)
363+
continue
364364

365-
if page_num >= len(writer.pages):
366-
page_num = len(writer.pages) - 1
365+
if page_num < 0 or page_num >= len(writer.pages):
366+
continue
367367

368-
# 添加书签
369-
# parent 是父级书签对象,用于处理多级目录
368+
# 添加书签,其中 parent 是父级书签对象,用于处理多级目录
370369
bookmark = writer.add_outline_item(title, page_num, parent=parent)
371370

372371
# 如果有子章节(children),递归添加
373372
if chapter.get("children"):
374-
_add_chapter(chapter["children"], parent=bookmark)
373+
add_chapter(chapter["children"], parent=bookmark)
375374

376375
# 开始处理章节数据
377-
_add_chapter(chapters)
376+
add_chapter(chapters)
378377

379378
# 保存修改后的文件
380379
with open(pdf_path, "wb") as f:
@@ -604,6 +603,7 @@ def set_access_token(token: str) -> str: # 设置并更新 Access Token
604603
return "Access Token 已保存!\n已写入文件:~/Library/Application Support/tchMaterial-parser/data.json"
605604
else:
606605
return "Access Token 已保存!\n本工具尚未支持该操作系统下 Access Token 的持久化,下次启动时仍需手动输入 Access Token。"
606+
607607
except Exception as e:
608608
print_error(e)
609609
return "Access Token 已保存!\n因出现错误而无法持久化,下次启动时仍需手动输入 Access Token。"
@@ -656,7 +656,7 @@ class resource_helper: # 获取网站上资源的数据
656656

657657
return parsed_hier
658658

659-
def fetch_lesson_list(self): # 获取课件列表(目前此函数代码存在问题)
659+
def fetch_lesson_list(self): # 获取课件列表
660660
# 获取课件层级数据
661661
tags_resp = session.get("https://s-file-1.ykt.cbern.com.cn/zxx/ndrs/tags/national_lesson_tag.json")
662662
tags_data = tags_resp.json()
@@ -675,17 +675,20 @@ class resource_helper: # 获取网站上资源的数据
675675
# 解析课件层级数据
676676
tag_paths: list[str] = [tag["tag_id"] for tag in sorted(lesson["tag_list"], key=lambda tag: tag["order_num"])]
677677

678-
# 分别解析课件层级
679-
temp_hier = parsed_hier["__internal_national_lesson"]
680-
for p in tag_paths:
681-
if temp_hier["children"] and temp_hier["children"].get(p):
682-
temp_hier = temp_hier["children"].get(p)
683-
if not temp_hier["children"]:
684-
temp_hier["children"] = {}
678+
# 分别解析课件层级(tag_paths 为乱序)
679+
def parse_tag_path(hier):
680+
for p in tag_paths:
681+
if hier["children"] and hier["children"].get(p):
682+
return parse_tag_path(hier["children"].get(p))
683+
return hier
684+
685+
hier = parse_tag_path(parsed_hier["__internal_national_lesson"])
686+
if not hier["children"]:
687+
hier["children"] = {}
685688

686689
lesson["display_name"] = lesson["title"] if "title" in lesson else lesson["name"] if "name" in lesson else f"(未知课件 {lesson['id']})"
687690

688-
temp_hier["children"][lesson["id"]] = lesson
691+
hier["children"][lesson["id"]] = lesson
689692

690693
return parsed_hier
691694

@@ -723,6 +726,18 @@ access_token = None
723726
headers = { "X-ND-AUTH": 'MAC id="0",nonce="0",mac="0"' } # 设置请求头部,包含认证信息,其中 “MAC id” 即为 Access Token,“nonce” 和 “mac” 不可缺省但可为任意非空值
724727
session.proxies = {} # 全局忽略代理
725728

729+
scale: float | None = None
730+
731+
# 在 Windows 上进行高 DPI 适配
732+
if os_name == "Windows" and win32print and win32gui and win32con and win32api and ctypes:
733+
scale = round(win32print.GetDeviceCaps(win32gui.GetDC(0), win32con.DESKTOPHORZRES) / win32api.GetSystemMetrics(0), 2) # 获取当前的缩放因子
734+
735+
# 调用 API 设置成由应用程序缩放
736+
try: # Windows 8.1 或更新
737+
ctypes.windll.shcore.SetProcessDpiAwareness(2)
738+
except Exception: # Windows 8 或更老
739+
ctypes.windll.user32.SetProcessDPIAware()
740+
726741
# 尝试加载已保存的 Access Token
727742
load_access_token()
728743

@@ -739,16 +754,7 @@ root = tk.Tk()
739754

740755
ui_font_family = pick_ui_font_family()
741756

742-
# 在 Windows 上进行高 DPI 适配
743-
if os_name == "Windows" and win32print and win32gui and win32con and win32api and ctypes:
744-
scale: float = round(win32print.GetDeviceCaps(win32gui.GetDC(0), win32con.DESKTOPHORZRES) / win32api.GetSystemMetrics(0), 2) # 获取当前的缩放因子
745-
746-
# 调用 API 设置成由应用程序缩放
747-
try: # Windows 8.1 或更新
748-
ctypes.windll.shcore.SetProcessDpiAwareness(2)
749-
except Exception: # Windows 8 或更老
750-
ctypes.windll.user32.SetProcessDPIAware()
751-
else: # 在非 Windows 操作系统上,通过 Tkinter 估算缩放因子
757+
if not scale: # 若获取缩放因子失败,通过 Tkinter 估算缩放因子
752758
try:
753759
scale: float = round(root.winfo_fpixels("1i") / 96.0, 2)
754760
except Exception:

0 commit comments

Comments
 (0)