这个应用的形态是:Electron 34 套一个 Vue 3 界面,真正的抓取逻辑全是 Python。
开发的时候很舒服:改 Vue 热更新,改 Python 下次点按钮就生效。打包发给别人是另一回事——对方电脑上没有 Python。
两层打包
第一层,Python 冻成 exe。
PyInstaller onedir 模式,输出到 build-backend/backend/,里面是一个 backend.exe 加一个 _internal/ 目录。
用 onedir 不用 onefile:onefile 每次启动都要把整个运行时解压到临时目录,启动慢,而且杀毒软件对”自解压的程序”格外敏感,误报率高得多。
第二层,electron-builder 把这个目录拷进 resources/backend/。
最终产物:
dist-electron/ SocialArchiver-1.2.5-win.zip # 解压即用 SocialArchiver-1.2.5-win.exe # NSIS 安装包 win-unpacked/ # 同内容,本机直接跑坑一:只拷 exe 一定坏
这是我这项目里被问得最多的问题。
有人从 win-unpacked 里把 Social Archiver.exe 单独拷到桌面,双击,报错。
Electron 的 exe 只是入口,它要去找同目录下的 resources/app.asar、resources/backend/backend.exe、_internal/ 里几千个 DLL 和 Python 模块。少任何一个都起不来。
所以文档里反复写:必须保留整个目录,要么发 zip,要么发安装包。
坑二:gallery-dl 装了两份
X 和 Instagram 都靠 gallery-dl。它被打进了冻结的后端里——但冻结的版本永远是打包那天的版本。
gallery-dl 更新很勤,平台一改接口它就得跟。冻结版没法 pip install -U。
所以运行时的策略是:先用 shutil.which('gallery-dl') 找系统里装的,找到就用系统的(用户可以自己升级);找不到才用冻结的兜底。
这样既能”解压即用、不用装 Python”,又能”想升级随时升”。
坑三:中文乱码
打包版有一段时间日志全是乱码。
原因:subprocess 在 Windows 上的默认编码跟着系统区域走,中文系统是 GBK,而管道里传的是 UTF-8。
修了两处:cli.py 里 _force_utf8_stdio() 强制重设 stdin/stdout,spawn 的时候显式指定编码。
还有个连带问题:stdout 是 JSON Lines,一行一条。如果缓冲区没行缓冲,一条消息可能被切成两半发出来,前端解析失败,界面一直转圈。所以 spawn 时开了行缓冲。
坑四:SmartScreen
安装包没有代码签名。
第一次运行,Windows 会弹「Windows 已保护你的电脑」。处理方式是「更多信息」→「仍要运行」。
这是预期行为,不是中毒。想消掉只有一条路:买 Authenticode 证书签 exe,一年几千块。个人项目不值当,所以在 README 里写清楚怎么绕过。
企业环境部署的话,可以在组策略里给这个 exe 加路径排除。
坑五:环境门卫
PyInstaller 打包前检查 Python 版本,低于 3.9 直接报错退出。
不检查的话,低版本打出来的包能生成,但运行时一堆语法错误,排查起来很痛苦。
坑六:输出目录被占用
win-unpacked 里的 exe 还在跑,再打包就失败——文件被锁。
解决方法是要么先关掉,要么指定临时输出目录:
npm run electron:build -- --config.directories.output=%TEMP%\sa-electron-out打完再拷回来。
打包本身的代码量不大,但它决定了别人能不能用。开发环境跑得通,和发给朋友能双击打开,中间隔着的全是这类细节。