From e0923754ccf207104760e0e71e3c952e95de749b Mon Sep 17 00:00:00 2001 From: GoForceX Date: Wed, 18 Oct 2023 17:26:42 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20:sparkles:=20=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=AF=BE=E6=9C=AC=E5=88=97=E8=A1=A8=E5=B9=B6?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E8=AF=BE=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bookHelper: 获取书本列表 parser: 添加书本选择区,通过获取的书本列表构建下载 URL --- releases/v1.3/bookHelper.py | 47 ++++++++++++ releases/v1.3/tchMaterial-parser.py | 107 ++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 releases/v1.3/bookHelper.py diff --git a/releases/v1.3/bookHelper.py b/releases/v1.3/bookHelper.py new file mode 100644 index 0000000..0f49fb4 --- /dev/null +++ b/releases/v1.3/bookHelper.py @@ -0,0 +1,47 @@ +import requests + +# 解析层级数据 +def parse_hierarchy(hier): + parsed = {} + + # 如果没有层级数据,返回空 + if not hier: + return None + for h in hier: + for ch in h['children']: + parsed[ch['tag_id']] = {'name': ch['tag_name'], 'children': parse_hierarchy(ch['hierarchies'])} + return parsed + +# 获取课本列表 +def fetch_book_list(): + # 获取层级数据 + tagsResp = requests.get('https://s-file-1.ykt.cbern.com.cn/zxx/ndrs/tags/tch_material_tag.json') + tagsData = tagsResp.json() + parsedHierarchy = parse_hierarchy(tagsData['hierarchies']) + + # 获取课本列表 URL 列表 + listResp = requests.get('https://s-file-2.ykt.cbern.com.cn/zxx/ndrs/resources/tch_material/version/data_version.json') + listData = listResp.json()['urls'].split(',') + + # 获取课本列表 + for url in listData: + bookResp = requests.get(url) + bookData = bookResp.json() + for i in bookData: + # 解析课本层级数据 + tagPaths = i['tag_paths'][0].split('/')[2:] + + # 如果课本层级数据不在层级数据中,跳过 + tempHier = parsedHierarchy[i['tag_paths'][0].split('/')[1]] + if not tagPaths[0] in tempHier['children']: + continue + + # 分别解析课本层级 + for p in tagPaths: + if tempHier['children'] and tempHier['children'].get(p): + tempHier = tempHier['children'].get(p) + if not tempHier['children']: + tempHier['children'] = {} + tempHier['children'][i['id']] = i + + return parsedHierarchy \ No newline at end of file diff --git a/releases/v1.3/tchMaterial-parser.py b/releases/v1.3/tchMaterial-parser.py index 53c385b..b0ebf50 100644 --- a/releases/v1.3/tchMaterial-parser.py +++ b/releases/v1.3/tchMaterial-parser.py @@ -4,6 +4,7 @@ # wuziqian211(https://space.bilibili.com/425503913) # 导入相关库 +from functools import partial import tkinter as tk from tkinter import ttk, messagebox, filedialog import threading @@ -13,6 +14,8 @@ import json import pyperclip +import bookHelper + # 获取操作系统类型 os_name = platform.system() @@ -116,6 +119,8 @@ def download(): failed_msg = "以下链接无法解析:\n" + "\n".join(failed_links) messagebox.showwarning("警告", failed_msg) # 显示警告对话框 +bookList = bookHelper.fetch_book_list() + # GUI root = tk.Tk() @@ -158,6 +163,108 @@ def download(): url_text = tk.Text(container_frame, width=70, height=12) # 添加URL输入框,长度和宽度不使用缩放!!! url_text.pack(padx=int(15 * scale), pady=int(15 * scale)) # 设置水平外边距、垂直外边距(跟随缩放) +# 构建选择项 +options = [['---'] + [bookList[k]['name'] for k in bookList.keys()], ['---'], ['---'], ['---'], ['---'], ['---']] + +variables = [tk.StringVar(root), tk.StringVar(root), tk.StringVar(root), tk.StringVar(root), tk.StringVar(root), tk.StringVar(root)] + +# 处理用户选择事件 +eventFlag = False # 防止事件循环调用 +def SelEvent(index, *args): + global eventFlag + + if eventFlag: + eventFlag = False # 检测到循环调用,重置标志位并返回 + return + + # 重置后面的选择项 + if variables[index].get() == '---': + for i in range(index + 1, len(drops)): + drops[i]['menu'].delete(0, 'end') + drops[i]['menu'].add_command(label='---', command=tk._setit(variables[i], '---')) + + eventFlag = True + variables[i].set('---') + # drops[i]['menu'].configure(state="disabled") + return + + # 更新选择项 + if index < len(drops) - 1: + currP1 = drops[index + 1] + + currHier = bookList + currID = [element for element in currHier if currHier[element]['name'] == variables[0].get()][0] + currHier = currHier[currID]['children'] + + endFlag = False # 是否到达最终目标 + for i in range(index): + try: + currID = [element for element in currHier if currHier[element]['name'] == variables[i + 1].get()][0] + currHier = currHier[currID]['children'] + except KeyError: # 无法继续向下选择,说明已经到达最终目标 + endFlag = True + + if endFlag: + currOptions = ['---'] + if not 'name' in currHier[list(currHier.keys())[0]]: + currOptions = ['---'] + [currHier[k]['title'] for k in currHier.keys()] + else: + currOptions = ['---'] + [currHier[k]['name'] for k in currHier.keys()] + + currP1['menu'].delete(0, 'end') + for choice in currOptions: + currP1['menu'].add_command(label=choice, command=tk._setit(variables[index + 1], choice)) + + # 到达目标,显示 URL + if endFlag: + currID = [element for element in currHier if currHier[element]['title'] == variables[index].get()][0] + url_text.insert('end', f'\nhttps://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial') + drops[-1]['menu'].delete(0, 'end') + drops[-1]['menu'].add_command(label='---', command=tk._setit(variables[-1], '---')) + variables[-1].set('---') + return + + # 重置后面的选择项 + for i in range(index + 2, len(drops)): + drops[i]['menu'].delete(0, 'end') + drops[i]['menu'].add_command(label='---', command=tk._setit(variables[i], '---')) + # drops[i]['menu'].configure(state="disabled") + + for i in range(index + 1, len(drops)): + eventFlag = True + variables[i].set('---') + + else: # 最后一项,必为最终目标,显示 URL + if variables[-1].get() == '---': + return + + currHier = bookList + currID = [element for element in currHier if currHier[element]['name'] == variables[0].get()][0] + currHier = currHier[currID]['children'] + for i in range(index - 1): + currID = [element for element in currHier if currHier[element]['name'] == variables[i + 1].get()][0] + currHier = currHier[currID]['children'] + + currID = [element for element in currHier if currHier[element]['title'] == variables[index].get()][0] + url_text.insert('end', f'https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial') + +# 绑定事件 +for index in range(6): + variables[index].trace_add('write', partial(SelEvent, index)) + +# 添加 Container +dropdown_frame = ttk.Frame(root) +dropdown_frame.pack(padx=int(10 * scale), pady=int(10 * scale)) + +drops = [] + +# 添加菜单栏 +for i in range(6): + drop = tk.OptionMenu( dropdown_frame , variables[i] , *options[i] ) + drop.grid(row=i // 3, column=i % 3, padx=int(15 * scale), pady=int(15 * scale)) # 设置位置,2行3列(跟随缩放) + variables[i].set('---') + drops.append(drop) + download_btn = ttk.Button(container_frame, text="下载", command=download) # 添加下载按钮 download_btn.pack(side="left", padx=int(40 * scale), pady=int(5 * scale), ipady=int(5 * scale)) # 设置水平外边距、垂直外边距(跟随缩放),设置按钮高度(跟随缩放) From fa9b0cc3564ff64b78d712810bee4488a0d8d6a4 Mon Sep 17 00:00:00 2001 From: GoForceX Date: Wed, 18 Oct 2023 17:39:09 +0800 Subject: [PATCH 2/3] =?UTF-8?q?style:=20=E5=8D=95=E5=BC=95=E5=8F=B7?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=8F=8C=E5=BC=95=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- releases/v1.3/bookHelper.py | 28 +++++------ releases/v1.3/tchMaterial-parser.py | 76 ++++++++++++++--------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/releases/v1.3/bookHelper.py b/releases/v1.3/bookHelper.py index 0f49fb4..65b25ce 100644 --- a/releases/v1.3/bookHelper.py +++ b/releases/v1.3/bookHelper.py @@ -8,20 +8,20 @@ def parse_hierarchy(hier): if not hier: return None for h in hier: - for ch in h['children']: - parsed[ch['tag_id']] = {'name': ch['tag_name'], 'children': parse_hierarchy(ch['hierarchies'])} + for ch in h["children"]: + parsed[ch["tag_id"]] = {"name": ch["tag_name"], "children": parse_hierarchy(ch["hierarchies"])} return parsed # 获取课本列表 def fetch_book_list(): # 获取层级数据 - tagsResp = requests.get('https://s-file-1.ykt.cbern.com.cn/zxx/ndrs/tags/tch_material_tag.json') + tagsResp = requests.get("https://s-file-1.ykt.cbern.com.cn/zxx/ndrs/tags/tch_material_tag.json") tagsData = tagsResp.json() - parsedHierarchy = parse_hierarchy(tagsData['hierarchies']) + parsedHierarchy = parse_hierarchy(tagsData["hierarchies"]) # 获取课本列表 URL 列表 - listResp = requests.get('https://s-file-2.ykt.cbern.com.cn/zxx/ndrs/resources/tch_material/version/data_version.json') - listData = listResp.json()['urls'].split(',') + listResp = requests.get("https://s-file-2.ykt.cbern.com.cn/zxx/ndrs/resources/tch_material/version/data_version.json") + listData = listResp.json()["urls"].split(",") # 获取课本列表 for url in listData: @@ -29,19 +29,19 @@ def fetch_book_list(): bookData = bookResp.json() for i in bookData: # 解析课本层级数据 - tagPaths = i['tag_paths'][0].split('/')[2:] + tagPaths = i["tag_paths"][0].split("/")[2:] # 如果课本层级数据不在层级数据中,跳过 - tempHier = parsedHierarchy[i['tag_paths'][0].split('/')[1]] - if not tagPaths[0] in tempHier['children']: + tempHier = parsedHierarchy[i["tag_paths"][0].split("/")[1]] + if not tagPaths[0] in tempHier["children"]: continue # 分别解析课本层级 for p in tagPaths: - if tempHier['children'] and tempHier['children'].get(p): - tempHier = tempHier['children'].get(p) - if not tempHier['children']: - tempHier['children'] = {} - tempHier['children'][i['id']] = i + if tempHier["children"] and tempHier["children"].get(p): + tempHier = tempHier["children"].get(p) + if not tempHier["children"]: + tempHier["children"] = {} + tempHier["children"][i["id"]] = i return parsedHierarchy \ No newline at end of file diff --git a/releases/v1.3/tchMaterial-parser.py b/releases/v1.3/tchMaterial-parser.py index b0ebf50..262a776 100644 --- a/releases/v1.3/tchMaterial-parser.py +++ b/releases/v1.3/tchMaterial-parser.py @@ -20,7 +20,7 @@ os_name = platform.system() # 如果是Windows操作系统,导入Windows相关库 -if os_name == 'Windows': +if os_name == "Windows": import win32print, win32gui, win32con, win32api, ctypes # 解析URL @@ -88,7 +88,7 @@ def download(): if len(urls) > 1: messagebox.showinfo("提示", "您选择了多个链接,将在选定的文件夹中使用教材名称作为文件名进行下载。") dir_path = filedialog.askdirectory() # 选择文件夹 - if os_name == 'Windows': + if os_name == "Windows": dir_path = dir_path.replace("/", "\\") if not dir_path: return @@ -107,7 +107,7 @@ def download(): else: default_filename = getDefaultFilename(contentId) or "download" save_path = filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF files", "*.pdf"), ("All files", "*.*")], initialfile=default_filename) # 选择保存路径 - if os_name == 'Windows': + if os_name == "Windows": save_path = save_path.replace("/", "\\") if not save_path: @@ -125,7 +125,7 @@ def download(): root = tk.Tk() # ----------高DPI适配start--------- -if os_name == 'Windows': +if os_name == "Windows": scale = round(win32print.GetDeviceCaps(win32gui.GetDC(0), win32con.DESKTOPHORZRES) / win32api.GetSystemMetrics(0), 2) # 获取屏幕缩放比例 # 调用api设置成由应用程序缩放 @@ -164,7 +164,7 @@ def download(): url_text.pack(padx=int(15 * scale), pady=int(15 * scale)) # 设置水平外边距、垂直外边距(跟随缩放) # 构建选择项 -options = [['---'] + [bookList[k]['name'] for k in bookList.keys()], ['---'], ['---'], ['---'], ['---'], ['---']] +options = [["---"] + [bookList[k]["name"] for k in bookList.keys()], ["---"], ["---"], ["---"], ["---"], ["---"]] variables = [tk.StringVar(root), tk.StringVar(root), tk.StringVar(root), tk.StringVar(root), tk.StringVar(root), tk.StringVar(root)] @@ -178,14 +178,14 @@ def SelEvent(index, *args): return # 重置后面的选择项 - if variables[index].get() == '---': + if variables[index].get() == "---": for i in range(index + 1, len(drops)): - drops[i]['menu'].delete(0, 'end') - drops[i]['menu'].add_command(label='---', command=tk._setit(variables[i], '---')) + drops[i]["menu"].delete(0, "end") + drops[i]["menu"].add_command(label="---", command=tk._setit(variables[i], "---")) eventFlag = True - variables[i].set('---') - # drops[i]['menu'].configure(state="disabled") + variables[i].set("---") + # drops[i]["menu"].configure(state="disabled") return # 更新选择项 @@ -193,64 +193,64 @@ def SelEvent(index, *args): currP1 = drops[index + 1] currHier = bookList - currID = [element for element in currHier if currHier[element]['name'] == variables[0].get()][0] - currHier = currHier[currID]['children'] + currID = [element for element in currHier if currHier[element]["name"] == variables[0].get()][0] + currHier = currHier[currID]["children"] endFlag = False # 是否到达最终目标 for i in range(index): try: - currID = [element for element in currHier if currHier[element]['name'] == variables[i + 1].get()][0] - currHier = currHier[currID]['children'] + currID = [element for element in currHier if currHier[element]["name"] == variables[i + 1].get()][0] + currHier = currHier[currID]["children"] except KeyError: # 无法继续向下选择,说明已经到达最终目标 endFlag = True if endFlag: - currOptions = ['---'] - if not 'name' in currHier[list(currHier.keys())[0]]: - currOptions = ['---'] + [currHier[k]['title'] for k in currHier.keys()] + currOptions = ["---"] + if not "name" in currHier[list(currHier.keys())[0]]: + currOptions = ["---"] + [currHier[k]["title"] for k in currHier.keys()] else: - currOptions = ['---'] + [currHier[k]['name'] for k in currHier.keys()] + currOptions = ["---"] + [currHier[k]["name"] for k in currHier.keys()] - currP1['menu'].delete(0, 'end') + currP1["menu"].delete(0, "end") for choice in currOptions: - currP1['menu'].add_command(label=choice, command=tk._setit(variables[index + 1], choice)) + currP1["menu"].add_command(label=choice, command=tk._setit(variables[index + 1], choice)) # 到达目标,显示 URL if endFlag: - currID = [element for element in currHier if currHier[element]['title'] == variables[index].get()][0] - url_text.insert('end', f'\nhttps://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial') - drops[-1]['menu'].delete(0, 'end') - drops[-1]['menu'].add_command(label='---', command=tk._setit(variables[-1], '---')) - variables[-1].set('---') + currID = [element for element in currHier if currHier[element]["title"] == variables[index].get()][0] + url_text.insert("end", f"\nhttps://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial") + drops[-1]["menu"].delete(0, "end") + drops[-1]["menu"].add_command(label="---", command=tk._setit(variables[-1], "---")) + variables[-1].set("---") return # 重置后面的选择项 for i in range(index + 2, len(drops)): - drops[i]['menu'].delete(0, 'end') - drops[i]['menu'].add_command(label='---', command=tk._setit(variables[i], '---')) - # drops[i]['menu'].configure(state="disabled") + drops[i]["menu"].delete(0, "end") + drops[i]["menu"].add_command(label="---", command=tk._setit(variables[i], "---")) + # drops[i]["menu"].configure(state="disabled") for i in range(index + 1, len(drops)): eventFlag = True - variables[i].set('---') + variables[i].set("---") else: # 最后一项,必为最终目标,显示 URL - if variables[-1].get() == '---': + if variables[-1].get() == "---": return currHier = bookList - currID = [element for element in currHier if currHier[element]['name'] == variables[0].get()][0] - currHier = currHier[currID]['children'] + currID = [element for element in currHier if currHier[element]["name"] == variables[0].get()][0] + currHier = currHier[currID]["children"] for i in range(index - 1): - currID = [element for element in currHier if currHier[element]['name'] == variables[i + 1].get()][0] - currHier = currHier[currID]['children'] + currID = [element for element in currHier if currHier[element]["name"] == variables[i + 1].get()][0] + currHier = currHier[currID]["children"] - currID = [element for element in currHier if currHier[element]['title'] == variables[index].get()][0] - url_text.insert('end', f'https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial') + currID = [element for element in currHier if currHier[element]["title"] == variables[index].get()][0] + url_text.insert("end", f"https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial") # 绑定事件 for index in range(6): - variables[index].trace_add('write', partial(SelEvent, index)) + variables[index].trace_add("write", partial(SelEvent, index)) # 添加 Container dropdown_frame = ttk.Frame(root) @@ -262,7 +262,7 @@ def SelEvent(index, *args): for i in range(6): drop = tk.OptionMenu( dropdown_frame , variables[i] , *options[i] ) drop.grid(row=i // 3, column=i % 3, padx=int(15 * scale), pady=int(15 * scale)) # 设置位置,2行3列(跟随缩放) - variables[i].set('---') + variables[i].set("---") drops.append(drop) download_btn = ttk.Button(container_frame, text="下载", command=download) # 添加下载按钮 From 15eec3c1b6dab40ebb7fbf108fe7177f00634819 Mon Sep 17 00:00:00 2001 From: GoForceX Date: Wed, 18 Oct 2023 17:41:15 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E9=95=BF=E5=B1=82=E7=BA=A7=E8=AF=BE?= =?UTF-8?q?=E6=9C=AC=E5=8A=A0=E6=8D=A2=E8=A1=8C=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- releases/v1.3/tchMaterial-parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/v1.3/tchMaterial-parser.py b/releases/v1.3/tchMaterial-parser.py index 262a776..d655673 100644 --- a/releases/v1.3/tchMaterial-parser.py +++ b/releases/v1.3/tchMaterial-parser.py @@ -246,7 +246,7 @@ def SelEvent(index, *args): currHier = currHier[currID]["children"] currID = [element for element in currHier if currHier[element]["title"] == variables[index].get()][0] - url_text.insert("end", f"https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial") + url_text.insert("end", f"\nhttps://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId={currID}&catalogType=tchMaterial&subCatalog=tchMaterial") # 绑定事件 for index in range(6):