@@ -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
723726headers = { "X-ND-AUTH" : 'MAC id="0",nonce="0",mac="0"' } # 设置请求头部,包含认证信息,其中 “MAC id” 即为 Access Token,“nonce” 和 “mac” 不可缺省但可为任意非空值
724727session .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
727742load_access_token ()
728743
@@ -739,16 +754,7 @@ root = tk.Tk()
739754
740755ui_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