style: 统一代码格式并改进异常处理
- 将多行字符串调整为符合PEP 8的格式 - 统一使用显式的异常捕获(except Exception) - 改进线程的daemon设置方式 - 移除未使用的异常变量和导入 - 修复文件末尾的换行符问题
This commit is contained in:
Binary file not shown.
Binary file not shown.
+11
-11
@@ -1,6 +1,7 @@
|
|||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
def download_file(url, filepath, referer=None, log_callback=None):
|
def download_file(url, filepath, referer=None, log_callback=None):
|
||||||
"""
|
"""
|
||||||
[Data Layer] 文件下载执行器
|
[Data Layer] 文件下载执行器
|
||||||
@@ -9,7 +10,11 @@ def download_file(url, filepath, referer=None, log_callback=None):
|
|||||||
try:
|
try:
|
||||||
# 根据不同平台可能需要调整 Headers
|
# 根据不同平台可能需要调整 Headers
|
||||||
headers = {
|
headers = {
|
||||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
"User-Agent": (
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/120.0.0.0 Safari/537.36"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
# 优先使用传入的 referer
|
# 优先使用传入的 referer
|
||||||
@@ -17,20 +22,14 @@ def download_file(url, filepath, referer=None, log_callback=None):
|
|||||||
headers["Referer"] = referer
|
headers["Referer"] = referer
|
||||||
else:
|
else:
|
||||||
# 简单的 Referer 区分 (保留旧逻辑作为后备)
|
# 简单的 Referer 区分 (保留旧逻辑作为后备)
|
||||||
if (
|
if "bilibili.com" in url or "hdslb.com" in url or "bilivideo.com" in url:
|
||||||
"bilibili.com" in url
|
|
||||||
or "hdslb.com" in url
|
|
||||||
or "bilivideo.com" in url
|
|
||||||
):
|
|
||||||
headers["Referer"] = "https://www.bilibili.com/"
|
headers["Referer"] = "https://www.bilibili.com/"
|
||||||
else:
|
else:
|
||||||
headers["Referer"] = "https://www.douyin.com/"
|
headers["Referer"] = "https://www.douyin.com/"
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
try:
|
try:
|
||||||
response = requests.get(
|
response = requests.get(url, headers=headers, stream=True, timeout=20)
|
||||||
url, headers=headers, stream=True, timeout=20
|
|
||||||
)
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
with open(filepath, "wb") as f:
|
with open(filepath, "wb") as f:
|
||||||
for chunk in response.iter_content(chunk_size=1024 * 1024):
|
for chunk in response.iter_content(chunk_size=1024 * 1024):
|
||||||
@@ -41,7 +40,8 @@ def download_file(url, filepath, referer=None, log_callback=None):
|
|||||||
if i == 2:
|
if i == 2:
|
||||||
if log_callback:
|
if log_callback:
|
||||||
log_callback(
|
log_callback(
|
||||||
f"下载请求失败: Status {response.status_code} | URL: {url[:30]}..."
|
f"下载请求失败: Status {response.status_code} "
|
||||||
|
f"| URL: {url[:30]}..."
|
||||||
)
|
)
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
if i == 2:
|
if i == 2:
|
||||||
@@ -53,4 +53,4 @@ def download_file(url, filepath, referer=None, log_callback=None):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if log_callback:
|
if log_callback:
|
||||||
log_callback(f"下载出错: {e}")
|
log_callback(f"下载出错: {e}")
|
||||||
return False
|
return False
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+14
-6
@@ -5,13 +5,17 @@ import json
|
|||||||
import requests
|
import requests
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from tkinter import messagebox
|
|
||||||
from DrissionPage import ChromiumPage, ChromiumOptions
|
from DrissionPage import ChromiumPage, ChromiumOptions
|
||||||
from src.downloader import download_file
|
from src.downloader import download_file
|
||||||
|
|
||||||
|
|
||||||
def run_bilibili_task(
|
def run_bilibili_task(
|
||||||
target_url, target_count, save_root, browser_path, log_callback, finish_callback
|
target_url,
|
||||||
|
target_count,
|
||||||
|
save_root,
|
||||||
|
browser_path,
|
||||||
|
log_callback,
|
||||||
|
finish_callback=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
[Control Layer] B站核心业务流程
|
[Control Layer] B站核心业务流程
|
||||||
@@ -85,7 +89,7 @@ def run_bilibili_task(
|
|||||||
next_btn.click()
|
next_btn.click()
|
||||||
no_new_data_count = 0
|
no_new_data_count = 0
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
no_new_data_count = 0
|
no_new_data_count = 0
|
||||||
@@ -146,7 +150,7 @@ def run_bilibili_task(
|
|||||||
if dp:
|
if dp:
|
||||||
try:
|
try:
|
||||||
dp.close()
|
dp.close()
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
# 这里需要一种机制通知UI线程结束,或者由UI层处理
|
# 这里需要一种机制通知UI线程结束,或者由UI层处理
|
||||||
@@ -218,7 +222,11 @@ def get_bilibili_play_url(bvid):
|
|||||||
"""
|
"""
|
||||||
url = f"https://www.bilibili.com/video/{bvid}"
|
url = f"https://www.bilibili.com/video/{bvid}"
|
||||||
headers = {
|
headers = {
|
||||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
"User-Agent": (
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/120.0.0.0 Safari/537.36"
|
||||||
|
),
|
||||||
"Referer": "https://www.bilibili.com/",
|
"Referer": "https://www.bilibili.com/",
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
@@ -242,4 +250,4 @@ def get_bilibili_play_url(bvid):
|
|||||||
return video_url, audio_url
|
return video_url, audio_url
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return None, None
|
return None, None
|
||||||
|
|||||||
+29
-11
@@ -5,7 +5,15 @@ from datetime import datetime
|
|||||||
from DrissionPage import ChromiumPage, ChromiumOptions
|
from DrissionPage import ChromiumPage, ChromiumOptions
|
||||||
from src.downloader import download_file
|
from src.downloader import download_file
|
||||||
|
|
||||||
def run_douyin_task(target_url, target_count, save_root, browser_path, log_callback, finish_callback):
|
|
||||||
|
def run_douyin_task(
|
||||||
|
target_url,
|
||||||
|
target_count,
|
||||||
|
save_root,
|
||||||
|
browser_path,
|
||||||
|
log_callback,
|
||||||
|
finish_callback,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
[Control Layer] 抖音核心业务流程
|
[Control Layer] 抖音核心业务流程
|
||||||
1. 启动浏览器
|
1. 启动浏览器
|
||||||
@@ -53,7 +61,7 @@ def run_douyin_task(target_url, target_count, save_root, browser_path, log_callb
|
|||||||
):
|
):
|
||||||
collected_works.append(aweme)
|
collected_works.append(aweme)
|
||||||
found_new = True
|
found_new = True
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
log_callback(f"已获取作品信息: {len(collected_works)}/{target_count}")
|
log_callback(f"已获取作品信息: {len(collected_works)}/{target_count}")
|
||||||
@@ -99,7 +107,11 @@ def run_douyin_task(target_url, target_count, save_root, browser_path, log_callb
|
|||||||
file_name_base = f"{date_str}({count_idx})"
|
file_name_base = f"{date_str}({count_idx})"
|
||||||
|
|
||||||
download_tasks.append(
|
download_tasks.append(
|
||||||
{"work": work, "index": index, "file_name_base": file_name_base}
|
{
|
||||||
|
"work": work,
|
||||||
|
"index": index,
|
||||||
|
"file_name_base": file_name_base,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# 使用线程池执行下载
|
# 使用线程池执行下载
|
||||||
@@ -115,7 +127,7 @@ def run_douyin_task(target_url, target_count, save_root, browser_path, log_callb
|
|||||||
len(works_to_process),
|
len(works_to_process),
|
||||||
save_root,
|
save_root,
|
||||||
task["file_name_base"],
|
task["file_name_base"],
|
||||||
log_callback
|
log_callback,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -133,12 +145,15 @@ def run_douyin_task(target_url, target_count, save_root, browser_path, log_callb
|
|||||||
if dp:
|
if dp:
|
||||||
try:
|
try:
|
||||||
dp.close()
|
dp.close()
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def process_douyin_work(work, index, total_count, save_root, file_name_base, log_callback):
|
|
||||||
|
def process_douyin_work(
|
||||||
|
work, index, total_count, save_root, file_name_base, log_callback
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
[Data Layer] 单个任务处理逻辑 (Worker)
|
[Data Layer] 单个任务处理逻辑 (Worker)
|
||||||
判断作品类型(视频/图文),生成路径并调用下载器
|
判断作品类型(视频/图文),生成路径并调用下载器
|
||||||
@@ -148,9 +163,11 @@ def process_douyin_work(work, index, total_count, save_root, file_name_base, log
|
|||||||
if "images" in work and work["images"]:
|
if "images" in work and work["images"]:
|
||||||
is_video = False
|
is_video = False
|
||||||
|
|
||||||
log_callback(
|
msg = (
|
||||||
f"[{index + 1}/{total_count}] {file_name_base} | {'视频' if is_video else '图文'} | 下载中..."
|
f"[{index + 1}/{total_count}] {file_name_base} | "
|
||||||
|
f"{'视频' if is_video else '图文'} | 下载中..."
|
||||||
)
|
)
|
||||||
|
log_callback(msg)
|
||||||
|
|
||||||
if is_video:
|
if is_video:
|
||||||
video_url = work["video"]["play_addr"]["url_list"][0]
|
video_url = work["video"]["play_addr"]["url_list"][0]
|
||||||
@@ -158,7 +175,7 @@ def process_douyin_work(work, index, total_count, save_root, file_name_base, log
|
|||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
if download_file(video_url, file_path, log_callback=log_callback):
|
if download_file(video_url, file_path, log_callback=log_callback):
|
||||||
log_callback(
|
log_callback(
|
||||||
f"[{index + 1}/{total_count}] {file_name_base} -> 下载完成"
|
f"[{index + 1}/{total_count}] {file_name_base} " "-> 下载完成"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
log_callback(
|
log_callback(
|
||||||
@@ -166,7 +183,8 @@ def process_douyin_work(work, index, total_count, save_root, file_name_base, log
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
log_callback(
|
log_callback(
|
||||||
f"[{index + 1}/{total_count}] {file_name_base} -> 文件已存在,跳过"
|
f"[{index + 1}/{total_count}] {file_name_base} "
|
||||||
|
"-> 文件已存在,跳过"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
img_folder = os.path.join(save_root, file_name_base)
|
img_folder = os.path.join(save_root, file_name_base)
|
||||||
@@ -185,4 +203,4 @@ def process_douyin_work(work, index, total_count, save_root, file_name_base, log
|
|||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_callback(f"[{index + 1}/{total_count}] {file_name_base} -> 处理出错: {e}")
|
log_callback(f"[{index + 1}/{total_count}] {file_name_base} -> 处理出错: {e}")
|
||||||
|
|||||||
Binary file not shown.
+10
-4
@@ -123,12 +123,18 @@ class DouyinDownloaderApp:
|
|||||||
frame_platform.pack(padx=10, pady=5, fill="x")
|
frame_platform.pack(padx=10, pady=5, fill="x")
|
||||||
|
|
||||||
rb_douyin = tk.Radiobutton(
|
rb_douyin = tk.Radiobutton(
|
||||||
frame_platform, text="抖音", variable=self.platform_var, value="douyin"
|
frame_platform,
|
||||||
|
text="抖音",
|
||||||
|
variable=self.platform_var,
|
||||||
|
value="douyin",
|
||||||
)
|
)
|
||||||
rb_douyin.pack(side="left", padx=10)
|
rb_douyin.pack(side="left", padx=10)
|
||||||
|
|
||||||
rb_bilibili = tk.Radiobutton(
|
rb_bilibili = tk.Radiobutton(
|
||||||
frame_platform, text="B站", variable=self.platform_var, value="bilibili"
|
frame_platform,
|
||||||
|
text="B站",
|
||||||
|
variable=self.platform_var,
|
||||||
|
value="bilibili",
|
||||||
)
|
)
|
||||||
rb_bilibili.pack(side="left", padx=10)
|
rb_bilibili.pack(side="left", padx=10)
|
||||||
|
|
||||||
@@ -223,8 +229,8 @@ class DouyinDownloaderApp:
|
|||||||
thread = threading.Thread(
|
thread = threading.Thread(
|
||||||
target=self.run_task,
|
target=self.run_task,
|
||||||
args=(url, int(count_str), save_path, browser_path, platform),
|
args=(url, int(count_str), save_path, browser_path, platform),
|
||||||
|
daemon=True,
|
||||||
)
|
)
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def run_task(self, target_url, target_count, save_root, browser_path, platform):
|
def run_task(self, target_url, target_count, save_root, browser_path, platform):
|
||||||
@@ -257,4 +263,4 @@ class DouyinDownloaderApp:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def finish_task(self, title, message):
|
def finish_task(self, title, message):
|
||||||
self.root.after(0, lambda: messagebox.showinfo(title, message))
|
self.root.after(0, lambda: messagebox.showinfo(title, message))
|
||||||
|
|||||||
+1
-1
@@ -13,4 +13,4 @@ def find_edge_path():
|
|||||||
for path in possible_paths:
|
for path in possible_paths:
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return path
|
return path
|
||||||
return None
|
return None
|
||||||
|
|||||||
+6
-3
@@ -2,10 +2,13 @@ import tkinter as tk
|
|||||||
from src.ui.app import DouyinDownloaderApp
|
from src.ui.app import DouyinDownloaderApp
|
||||||
|
|
||||||
# 运行脚本 (使用 my_env 环境):
|
# 运行脚本 (使用 my_env 环境):
|
||||||
# D:\ProgramData\anaconda3\envs\my_env\python.exe "D:\Code\doing_exercises\programs\Video Downloader\video_downloader.py"
|
# D:\ProgramData\anaconda3\envs\my_env\python.exe video_downloader.py
|
||||||
#
|
#
|
||||||
# 打包成 exe (使用 my_env 环境):
|
# 打包成 exe (使用 my_env 环境):
|
||||||
# D:\ProgramData\anaconda3\envs\my_env\python.exe -m nuitka --standalone --mingw64 --show-memory --show-progress --output-dir=build_nuitka --enable-plugin=tk-inter --include-data-dir=ico=ico --windows-icon-from-ico=ico\video_downloader.ico --main=video_downloader.py
|
# D:\ProgramData\anaconda3\envs\my_env\python.exe -m nuitka --standalone ^
|
||||||
|
# --mingw64 --show-memory --show-progress --output-dir=build_nuitka ^
|
||||||
|
# --enable-plugin=tk-inter --include-data-dir=ico=ico ^
|
||||||
|
# --windows-icon-from-ico=ico\video_downloader.ico --main=video_downloader.py
|
||||||
|
|
||||||
# 主函数入口
|
# 主函数入口
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -13,7 +16,7 @@ if __name__ == "__main__":
|
|||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
app = DouyinDownloaderApp(root)
|
app = DouyinDownloaderApp(root)
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
with open("error_log.txt", "w") as f:
|
with open("error_log.txt", "w") as f:
|
||||||
|
|||||||
Reference in New Issue
Block a user