用法,将需要下载的链接批量保存到一个txt文件中,一行一条下载文件的链接,例如

360截图20250530190744733.jpg (15.15 KB, 下载次数: 0)
下载附件
2025-5-30 19:09 上传
https://www.test.cn/1.png
https://www.test.cn/image/2.png
会自动下载到软件目录中的downloads文件夹会根据链接生成对于的目录例如上面的下载的文件会自动保存到downloads/1.png和downloads/image/2.png
源码如下:
[Python] 纯文本查看 复制代码import tkinter as tk
from tkinter import filedialog, scrolledtext
import threading
from urllib.parse import urlparse, unquote
import os
import requests
import concurrent.futures
import chardet
class DownloaderApp:
def __init__(self, master):
self.master = master
master.title("文件下载器")
self.setup_ui()
def setup_ui(self):
# 上传按钮
self.upload_button = tk.Button(self.master, text="上传txt文件", command=self.upload_file)
self.upload_button.pack(pady=10)
# 线程数设置
self.thread_frame = tk.Frame(self.master)
self.thread_frame.pack(pady=5)
self.thread_label = tk.Label(self.thread_frame, text="线程数:")
self.thread_label.pack(side=tk.LEFT)
self.thread_num = tk.IntVar(value=5)
self.thread_spin = tk.Spinbox(self.thread_frame, from_=1, to=20,
textvariable=self.thread_num, width=5)
self.thread_spin.pack(side=tk.LEFT, padx=5)
# 日志显示区域
self.log_text = scrolledtext.ScrolledText(self.master, height=15, wrap=tk.WORD)
self.log_text.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
self.log_text.config(state=tk.DISABLED)
def upload_file(self):
filepath = filedialog.askopenfilename(filetypes=[("文本文件", "*.txt")])
if not filepath:
return
try:
# 修改这里:添加encoding参数指定编码
with open(filepath, 'r', encoding='utf-8') as f:
urls = [line.strip() for line in f if line.strip()]
except UnicodeDecodeError:
# 如果UTF-8失败,尝试用GB18030编码(兼容GBK)
try:
with open(filepath, 'r', encoding='gb18030') as f:
urls = [line.strip() for line in f if line.strip()]
except Exception as e:
self.log(f"错误:无法解码文件 - {e}")
return
except Exception as e:
self.log(f"错误:无法读取文件 - {e}")
return
if not urls:
self.log("错误:文件中没有有效的URL")
return
# 获取线程数并启动下载
thread_count = self.thread_num.get()
download_thread = threading.Thread(target=self.start_download,
args=(urls, thread_count))
download_thread.start()
def start_download(self, urls, thread_count):
with concurrent.futures.ThreadPoolExecutor(max_workers=thread_count) as executor:
executor.map(self.download_file, urls)
def detect_encoding(filepath):
with open(filepath, 'rb') as f:
result = chardet.detect(f.read())
return result['encoding']
def download_file(self, url):
try:
parsed = urlparse(url)
path = unquote(parsed.path)
path = os.path.normpath(path).replace('\\', '/')
dir_name = os.path.dirname(path)
file_name = os.path.basename(path)
if not file_name or file_name == '.':
file_name = 'index.html'
local_dir = os.path.join('downloads', dir_name.lstrip('/'))
os.makedirs(local_dir, exist_ok=True)
response = requests.get(url, timeout=10)
response.raise_for_status()
local_path = os.path.join(local_dir, file_name)
with open(local_path, 'wb') as f:
f.write(response.content)
self.log(f"✅ 下载成功:{local_path}")
except requests.exceptions.RequestException as e:
self.log(f"❌ 下载失败:{url} - 网络错误:{e}")
except Exception as e:
self.log(f"❌ 下载失败:{url} - 错误:{e}")
def log(self, message):
self.master.after(0, self._update_log, message)
def _update_log(self, message):
self.log_text.config(state=tk.NORMAL)
self.log_text.insert(tk.END, message + "\n")
self.log_text.config(state=tk.DISABLED)
self.log_text.see(tk.END)
if __name__ == "__main__":
root = tk.Tk()
app = DownloaderApp(root)
root.mainloop()
成品下载:https://xbl.lanzoue.com/iD21Y2xkxa9i 密码:e2f8