把抖音「收藏表情」批量导出成本地文件,自动转成微信可直接发送的格式(动态转 GIF、静态转 PNG)。
两个部件完全解耦:
1. 油猴脚本 → 导出 emoji-list.json
↓
2. douyin-emoji-exporter.exe → 下载 + 转换 + 写入独立文件夹
两者之间只通过一个 JSON 文件交接 —— 不需要同时运行,不需要登录态,转换器可以随时重跑。
emoji-list-xxx.jsondouyin-emoji-exporter.exeemoji-list_<日期>-<时间>\ 里单文件 exe,22 MB,无需安装,无需 Python。
也可以只用源码:
pip install -r converter/requirements.txt后运行python converter/convert.py <清单.json>
Ctrl+Shift+E 快捷键emoji-list-*.json 文件表情面板是滚动加载的。脚本会自动滚到底并等待列表稳定(连续 3 轮数量不再增加才停),所以正常情况下不需要手动滑。
如果仍然不全,先手动滑到最底部再点抓取。
把脚本导出的 emoji-list-xxx.json 直接拖到 douyin-emoji-exporter.exe 上。
程序会在 exe 同级目录下新建一个文件夹(名字带清单名和时间戳),产物就在里面:
(exe 所在目录)\
├── douyin-emoji-exporter.exe
└── emoji-list_1026-0030\ ← 产物在这里
├── emoji_0001.gif
├── emoji_0002.gif
├── ...
└── _report.txt
窗口会显示统计,看完按回车关闭。重复拖放不会覆盖,每次生成新文件夹。
不需要 Python,不需要命令行。
douyin-emoji-exporter.exe emoji-list.json # 基本用法
douyin-emoji-exporter.exe emoji-list.json --max-side 240 # 带参数
douyin-emoji-exporter.exe --help # 全部参数
| 参数 | 作用 |
|---|---|
--static-format webp |
静态图改用 WebP(省约 30% 体积,无损) |
--format webp |
动图也保留原格式(体积最小,但微信动态 WebP 不会动) |
--max-side 240 |
最大边长 240px,GIF 体积大幅下降 |
--max-frames 30 |
动图最多 30 帧(抽帧,动画会变卡) |
--max-mb 5 |
单文件超过 5MB 时自动降采样 |
--workers 8 |
并发线程数(默认 4) |
cd converter
pip install pillow requests
python convert.py input/emoji-list.json
GIF 格式本身决定了动图会比较大。 这是格式限制,不是程序问题。
实测 86 张表情(42 动图 + 44 静态,保留原始尺寸):
| 输出配置 | 总体积 | 说明 |
|---|---|---|
| 默认(动图 GIF + 静态 PNG) | 145.4 MB | GIF 130.3 MB + PNG 15.1 MB |
--static-format webp |
140.9 MB | 静态图从 15.1 降到 10.7 MB |
--max-side 240 |
约 73 MB | 缩到 240px,聊天窗口够用 |
--format webp |
约 22 MB | 保留原始体积,但微信动态 WebP 不会动 |
为什么 GIF 这么大:GIF 是帧间独立的,每帧都要完整存一张 256 色调色板图。实测「字节/像素/帧」稳定在 0.5~1.0,一个 148 帧、236×426 的动画,转成 GIF 必然接近 11MB。这个系数由 GIF 格式决定,换任何语言都改变不了。
怎么选:
--format webp,体积最小且完全无损--max-side 240静态图默认 PNG(兼容性最好,任何软件都能打开)。改 --static-format webp 可省约 30% 体积,且是无损重编码,画质与 PNG 一致。
Release 提供的是 PyInstaller onefile 单文件版:douyin-emoji-exporter.exe,22 MB。下载下来就是这一个 exe,没有任何依赖库目录或附加文件。
体积对比:
| 方案 | 体积 | 能否处理动画 WebP |
|---|---|---|
| Python + PyInstaller(onefile) | 22 MB 单文件 | ✅ 可以(Pillow 完整支持) |
| Python + PyInstaller(onedir) | 46 MB 目录(90 个文件) | ✅ 可以,但要多带一堆文件 |
| Go(仅标准库) | 9.6 MB | ❌ 不支持 |
| Go(+ x/image/webp) | 2.6 MB | ❌ 只能解第一帧,动画报错 |
为什么不用 Go:抖音的表情全部是动画 WebP。实测 golang.org/x/image/webp 对动画 WebP 直接报 webp: invalid format,只能解第一帧。要用 Go 处理只能 CGO 绑 libwebp(捆 DLL、失去静态单文件优势)或自己实现 RIFF/ANMF + VP8 解码(等于重写解码器)。Pillow 开箱即用完整支持动画 WebP、透明通道和自适应调色板量化。
关于 onefile 的启动:单文件版启动时要把自身内容解压到临时目录,因此首次启动会比带库目录的版本慢 1~2 秒,属正常现象。打包时已用 --runtime-tmpdir "." 指定为 exe 所在目录,避免某些系统上默认临时目录不可写导致的 Could not create temporary directory! 报错;程序退出会自动清理,不会残留文件。
id 去重--static-format 改 WebP).tmp 再原子替换,避免中断留下半个文件_report.txt,记录每个文件的大小/帧数/来源 URL仓库内容(源码):
douyin-emoji-exporter/
├── userscript/
│ └── douyin-emoji-exporter.user.js 油猴脚本(抓 URL → JSON)
├── converter/
│ ├── convert.py 转换器源码
│ ├── requirements.txt
│ └── input/emoji-list.json 清单格式示例
├── README.md
└── LICENSE
Release 下载的就是这一个文件:
douyin-emoji-exporter.exe 单文件,22 MB,免安装
把它放在任意目录,然后把 emoji-list-*.json 拖上去即可。
产物位置:emoji-list_<日期>-<时间>\(和 exe 同级)
{
"version": 1,
"captured_at": "2026-10-26T00:10:00+08:00",
"source": "https://www.douyin.com/",
"total": 86,
"animated": 42,
"static": 44,
"items": [
{
"id": "o8BABlJUEEMAAjdQZ4TfEFz0DDehBeI1H9sKrA",
"url": "https://p26-im-emoticon-sign.byteimg.com/...",
"w": 240,
"h": 240,
"animated": true
}
]
}
id 取自 URL 中 ~tplv 之前那段(实测 86 个全部唯一)。不能用路径末段——那是 resize 参数,很多表情相同。
Q:转换时大量 403?
签名 URL 的 x-expires 到期了(实测约 1 年)。重新抓一次即可。
Q:脚本抓到的表情不全? 先手动把表情面板滑到最底部,再点抓取。
Q:能不能不装油猴?
可以。直接把 emoji-list.json 里的 items 手填 URL 就行,转换器不关心 URL 从哪来。
Q:GIF 太大想压小?
用 --max-side 240 或 --max-frames 30(抽帧)。注意抽帧会让动画不流畅。
Q:静态图体积能再小点吗?
加 --static-format webp,省约 30% 且完全无损。