从零打造抖音视频下载器:一个 Python GUI 工具的开发手记
📅发布时间:2026-05-07
🏷️标签:Python / GUI / PyInstaller / Playwright / 爬虫
💡适合人群:想用 Python 开发桌面工具、解决实际问题的人,该工具仅限于学习研究
一、缘起:为什么我要做这个工具?
起因很简单——我需要一个不需要复杂操作的抖音视频下载器。
现有的方案要么需要装各种依赖,要么要手动复制 Cookie,要么下载下来有水印。找了一圈,发现 f2 这个 Python 库是最靠谱的无水印下载方案,但它只有命令行界面。
于是我想:能不能做一个带图形界面的 exe,双击就能用?
二、技术方案选型
核心需求
| 需求 | 解决方案 |
|---|---|
| 无水印下载 | f2Python 库 |
| 图形界面 | Tkinter(Python 内置,零依赖) |
| 自动获取 Cookie | playwright浏览器自动化 |
| 打包成 exe | PyInstaller |
为什么选 Tkinter 而不是 PyQt?
最初考虑过 PyQt/PySide,界面会更漂亮。但最终选择 Tkinter 的理由很简单:
- 零依赖:Python 内置,不需要额外装任何东西
- 打包体积小:PyQt 打包后动不动 200MB+,Tkinter 只要 140MB
- 够用就好:这个工具界面简单,Tkinter 完全能满足
三、核心代码实现
1. 主界面(Tkinter)
importtkinterastkfromtkinterimportttk,messagebox,filedialog,scrolledtextclassDouyinDownloaderApp(tk.Tk):def__init__(self):super().__init__()self.title("抖音视频无水印下载器 v1.0")self.geometry("750x620")# 核心组件:链接输入、Cookie输入、保存路径、日志输出# ...(完整代码见文末)def_start_download(self):url=self.video_url.get().strip()cookie=self.txt_cookie.get("1.0",tk.END).strip()save_path=self.save_path.get().strip()# 调用 f2 下载thread=threading.Thread(target=run_f2_download,args=(url,cookie,save_path,self.txt_log),daemon=True,)thread.start()2. 关键问题:PyInstaller 打包后 sys.executable 指向 exe 本身
打包后最头疼的问题出现了——sys.executable不再是python.exe,而是打包出来的 exe 本身,导致无法通过python -m f2调用 f2。
解决方案:写一个 Python 路径查找器
importsys,os,shutildef_find_python_executable()->str:""" PyInstaller 打包后,sys.executable 指向 exe 本身, 需要手动查找本机 Python 路径。 """# 如果是开发环境(未打包),直接用 sys.executableifnotgetattr(sys,"frozen",False):returnsys.executable# 打包场景:从常见路径中查找 Pythoncommon_paths=[r"D:\Python\Python311\python.exe",r"D:\Python\Python310\python.exe",r"C:\Python311\python.exe",]forpincommon_paths:ifos.path.isfile(p):returnp# 从系统 PATH 搜索which_python=shutil.which("python")ifwhich_python:returnwhich_pythonraiseFileNotFoundError("未找到 Python 解释器")3. URL 格式自动转换
用户经常发来精选页链接(/jingxuan?modal_id=xxx),但 f2 只认识视频页链接(/video/xxx)。加一个转换器:
fromurllib.parseimporturlparse,parse_qsdef_normalize_douyin_url(url:str)->str:"""将精选页/话题页链接转换为视频页链接"""parsed=urlparse(url)# 如果已经是视频页,直接返回if"/video/"inparsed.path:returnurl# 从 modal_id 提取视频 IDif"modal_id"inparsed.query:modal_id=parse_qs(parsed.query).get("modal_id",[None])[0]ifmodal_id:returnf"https://www.douyin.com/video/{modal_id}"returnurl4. Playwright 自动获取 Cookie
最实用的功能——点击按钮自动从浏览器提取 Cookie:
fromplaywright.sync_apiimportsync_playwright KEY_COOKIES=["ttwid","odin_tt","passport_csrf_token","__ac_nonce","__ac_signature","s_v_web_id"]deffetch_cookies_auto(on_log=None)->str|None:"""打开浏览器,访问抖音,自动提取 Cookie"""withsync_playwright()asp:browser=p.chromium.launch(headless=False)context=browser.new_context()page=context.new_page()page.goto("https://www.douyin.com/",wait_until="domcontentloaded")time.sleep(3)# 等待 Cookie 加载cookies=context.cookies(["https://www.douyin.com"])cookie_str="; ".join(f"{c['name']}={c['value']}"forcincookiesifc["name"]inKEY_COOKIES)returncookie_str四、打包配置(PyInstaller)
# 抖音下载器.spec a = Analysis( ['douyin_downloader_gui.py'], hiddenimports=[ 'f2.cli', 'f2.utils', 'playwright', 'playwright.sync_api', 'tkinter', '_tkinter', ], ) exe = EXE(pyz, a.scripts, [], name='抖音下载器', console=False, # 不显示控制台黑窗口 ) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, name='抖音下载器', )打包命令:
pyinstaller 抖音下载器.spec五、踩坑总结
| 坑 | 原因 | 解决方案 |
|---|---|---|
| f2 调用失败 | 打包后 sys.executable 指向 exe | 自定义 Python 路径查找器 |
| 精选页链接下载失败 | modal_id 格式不被 f2 识别 | URL 预处理转换 |
| 浏览器 Cookie 数据库锁定 | Chrome 正在运行时无法读取 | 改用 Playwright 启动独立浏览器 |
| 打包体积过大 | PyQt + Playwright | 用 Tkinter + 精简 hiddenimports |
六、使用效果
最终交付的是一个144MB 的文件夹,包含:
抖音下载器.exe— 双击即用_internal/— 依赖库(内置 Chromium 浏览器)
使用流程(从 5 步简化为 1 步):
旧流程:复制链接 → 打开浏览器 F12 → 找 Cookie → 拼字符串 → 粘贴 → 下载 新流程:点「自动获取 Cookie」→ 粘贴链接 → 下载七、源码获取
完整源码已开源,有需要的朋友可以自行下载研究:
📦项目文件:https://github.com/wupengfei-alt/douyin-downloader
核心文件说明:
| 文件 | 说明 |
|---|---|
douyin_downloader_gui.py | 主程序(含 GUI + 下载逻辑) |
playwright_helper.py | Cookie 自动获取模块 |
build.bat | 一键打包脚本 |
抖音下载器.spec | PyInstaller 配置文件 |
八、写在最后
这个项目从想法到完成,花了大半天时间。中间遇到了不少坑,但每一个都学到了东西:
- PyInstaller 的 sys.executable 陷阱— 这个坑很少有人提,但一旦遇到就傻眼
- Tkinter 的线程安全— 所有耗时操作都要丢到子线程,GUI 只负责展示
- 自动化 Cookie 获取— 用 Playwright 替代手动复制,体验提升明显
技术不一定非要多么高大上,能解决实际问题就是好技术。希望这篇文章对你有帮助!
如果你也有类似的需求想要实现,欢迎评论区交流!
原创不易,转载记得注明出处。