[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-94512":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":14,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":20,"topics":21,"createdAt":10,"pushedAt":10,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":14,"starSnapshotCount":14,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},94512,"mufy-batch-export","willwefind\u002Fmufy-batch-export","willwefind","把 mufy 的聊天记录批量导出成 Markdown + JSON 的油猴脚本","",null,"JavaScript",131,1,0,30,43.9,"MIT License",false,"main",true,[],"2026-08-24 04:01:22","# Mufy 批量导出\n\n把 mufy 上**所有角色的聊天记录**一次性导出来，存成能长期保存、能当小说翻的文件。\n\nmufy 自带的导出只能在存档列表里一条一条点。角色多、存档多的时候基本没法用。\n\n> ## 📱 只有手机也能用 —— 全程\n>\n> **不需要电脑。** 装脚本 → 导出 → 转成电子书 → 读，**整条链路在手机上就能闭环**，\n> iPhone 和安卓**都有用户实际走通过**。\n> 很多人以为这是个\"电脑工具\"就直接关掉了，其实不是。\n>\n> 👉 **手机用户直接看这一节：[附：手机上全程走完](#附手机上全程走完iphone--安卓两边都有人走通)**\n> （iPhone 用 Safari + Userscripts，安卓用 X浏览器 \u002F Via \u002F 火狐+篡改猴，都有分步教程）\n\n> ## ⏳ 想导就趁早\n>\n> mufy 公告过迁移服务器会丢一部分聊天记录，已经有用户的早期记录**在两条路上都取不回来了**\n> （这个脚本和 mufy 官方自己的导出都拿不到）。\n> **导出来放在自己硬盘上的那一份，才是不会变的那一份。**\n\n> ⚠️ 非官方工具，和 mufy 官方无关。它走的是网页自己在用的接口，官方改接口就可能失效。\n> 只读你自己的账号数据。\n>\n> 🔞 **面向成年用户。请勿向未成年人传播本工具或站点地址。**\n\n---\n\n## 目录\n\n0. 📱 **[只有手机也能用（全程）](#附手机上全程走完iphone--安卓两边都有人走通)** —— **没有电脑照样能导、能读；很多人漏了这条**\n1. [先读这一段，能省你很多时间](#先读这一段能省你很多时间) —— 这仓库里没有 App，先搞清楚要用什么\n2. [第一步：导出你的聊天记录（电脑上）](#第一步导出你的聊天记录电脑上) —— 装插件 → 装脚本 → 开始导（**新手从这儿开始**；**没出现按钮**的看这一节里的 🚨 大红框）\n3. [第二步之 A：用网页阅读器翻看](#第二步之-a用网页阅读器翻看) —— 直接读 zip 不用解压，**手机也能用**\n4. [第二步之 B：转成电子书，在手机上读](#第二步之-b转成电子书在手机上读) —— EPUB，导进微信读书当小说翻\n5. [导出的东西长什么样](#导出的东西长什么样) —— 解开压缩包是什么结构\n6. [顺带：把人设面具也导出来](#顺带把人设面具也导出来) —— 含「没订阅只导得出几个」的说明\n7. [你自己写的角色卡](#你自己写的角色卡) —— 全字段明文＋图片；也讲了官方引继码为什么不够\n8. [导进酒馆（SillyTavern \u002F Tavo 之类）](#导进酒馆sillytavern--tavo-之类) —— 含「能不能接着聊」要先知道的三件事\n9. [聊天记录不受这个限制（连\"已经找不到的角色\"都导得出来）](#聊天记录不受这个限制连已经找不到的角色都导得出来) —— 哪些拿得到、哪些拿不到\n10. [⚠️ 最重要的一件事：你现有的备份可能是缺的](#️-最重要的一件事你现有的备份可能是缺的) —— **用别的办法导的备份，很可能少一块**\n11. [常见问题](#常见问题) —— 导不出、乱码、文件对不上号、报错看不懂、**会不会被封号（不会，附一例真实误会）**，都在这儿\n12. [附：手机上全程走完（iPhone \u002F 安卓，两边都有人走通）](#附手机上全程走完iphone--安卓两边都有人走通) —— 只有手机也能用\n13. [License](#license)\n\n---\n\n## 先读这一段，能省你很多时间\n\n**这个仓库里没有「App」。** 点开 `make-epub.py` 或 `mufy-batch-export.user.js` 会看到一屏\n代码——**那是正常的**，它们是「代码文件」，不是应用程序，点开只会看到文字。\n\n要用它们，得让**浏览器**去跑（下面第一步会教）。\n\n| 你想做什么 | 需要什么 | 能在手机上做吗 |\n|---|---|---|\n| **导出聊天记录** | 浏览器 + 一个能跑脚本的扩展 | ✅ 可以（见[手机教程](#附手机上全程走完iphone--安卓两边都有人走通)） |\n| **导出人设面具** | 同上（**v1.11 新增**） | ✅ 可以 |\n| **导出你自己写的角色卡** | 同上（**v1.12 新增**） | ✅ 可以 |\n| **转成电子书（EPUB）** | 同上，**v1.10 起不用装 Python 了** | ✅ 可以 |\n| **用网页阅读器翻看** | 浏览器 | ✅ 可以（手机上用「**直接选 zip 文件**」**多选整包**，别用「选择文件夹」） |\n| **在手机上读电子书** | 微信读书 \u002F 图书 \u002F 静读天下 | ✅ 可以 |\n\n**一句话：全都能在手机上做。** 有电脑就照下面的正文走（屏幕大、批量导几百个角色更稳）；\n**只有手机就直接跳到 [附：手机上全程走完](#附手机上全程走完iphone--安卓两边都有人走通)**，\n那一节是从零开始的分步教程，iPhone 和安卓分开写。\n\n---\n\n## 第一步：导出你的聊天记录（电脑上）\n\n> 📱 **只有手机？这一节可以跳过** —— 直接看\n> **[附：手机上全程走完](#附手机上全程走完iphone--安卓两边都有人走通)**，那边是从零开始的分步教程。\n\n### 1. 装一个浏览器插件\n\n用电脑打开 Chrome 或 Edge，安装 **Tampermonkey（篡改猴）**：\n\n\u003Chttps:\u002F\u002Fwww.tampermonkey.net\u002F>\n\n点进去选你的浏览器，按提示装上。装完浏览器右上角会多一个灰黑色的图标。\n\n> **装完还有一步，很多人卡在这儿：浏览器默认不允许扩展运行用户脚本。**\n>\n> - **Chrome 138 及以上**：地址栏输 `chrome:\u002F\u002Fextensions` → 找到 Tampermonkey →\n>   点「**详细信息**」→ 打开「**允许用户脚本**」开关。\n> - **更早的 Chrome**：同一页右上角打开「**开发者模式**」。\n> - **Edge**：地址栏输 `edge:\u002F\u002Fextensions` → 左下角打开「**开发人员模式**」。\n>\n> 没开这个开关的表现很迷惑人：脚本明明装上了、Tampermonkey 面板里也看得见，\n> 但 mufy 页面左下角**就是不出现**那个「⬇ 批量导出」按钮。\n> 一发现按钮不出来，先回来检查这一项。\n\n### 2. 装脚本\n\n点这个链接：\n\n\u003Chttps:\u002F\u002Fraw.githubusercontent.com\u002Fwillwefind\u002Fmufy-batch-export\u002Fmain\u002Fmufy-batch-export.user.js>\n\nTampermonkey 会自动弹出一个安装页面，点 **安装** 就好。\n\n> 如果没弹安装页、只看到一屏代码，说明 Tampermonkey 没装好或没启用。\n> 那就手动来：点浏览器右上角的 Tampermonkey 图标 →「添加新脚本」→\n> 把那一屏代码**全选复制**粘进去 → 按 `Ctrl+S` 保存。\n\n> 🌏 **那个链接打不开？显示「无法访问此页面 \u002F `DNS_PROBE_FINISHED_NXDOMAIN`」？**\n>\n> **不是你网址打错了，也不是篡改猴的问题**，是你的网络连不上\n> `raw.githubusercontent.com` 这个域名——**它和 github.com 是两个域名，\n> 经常一个通一个不通**（能打开仓库首页、却打不开这个链接，就是这种情况）。\n> 篡改猴这时会说「没有访问此页面的权限」，那只是因为当前页是个错误页，没脚本可装。\n>\n> **绕开它，一分钟装好：**\n>\n> 1. 回到**仓库首页**（github.com 那个，你既然能看到这份说明就说明它是通的）\n> 2. 点开 **`mufy-batch-export.user.js`** 这个文件\n> 3. 代码区右上角有一排小按钮，点那个**复制图标**（把整份代码复制到剪贴板）\n>    —— ⚠️ **别点 Raw 和 Download，那两个还是会跳到打不开的那个域名**\n> 4. 点浏览器右上角的**篡改猴图标 →「添加新脚本…」**\n> 5. 把编辑器里自带的那几行**全选删掉**，粘贴，按 `Ctrl+S` 保存\n> 6. 回 mufy 页面刷新，左下角就有按钮了\n>\n> 另外也可以试试这个**镜像地址**（内容和上面那个链接一模一样，我们核对过字节数）：\n> `https:\u002F\u002Fcdn.jsdelivr.net\u002Fgh\u002Fwillwefind\u002Fmufy-batch-export@main\u002Fmufy-batch-export.user.js`\n> ——⚠️ 但**我们没法保证你的网络能通它**，通不了就走上面那六步。\n>\n> ⚠️ **这样手动装的脚本不会自动更新**（自动更新也要走那个域名）。\n> 以后想升级，把上面六步再走一遍就行。\n\n#### 以前装过的，要不要重装？\n\n看你要什么，说清楚免得白折腾：\n\n- **只导聊天记录 \u002F EPUB**：建议升，这几版修的都是真问题：\n  - **v1.13**：以前一个角色出错，整批就停在那儿，后面的角色一个都不会再试。\n    现在会跳过继续跑，结尾报清成功／失败。\n  - **v1.14**：面板底部多了「⬇ 手动保存」链接——万一自动下载没成功（有人遇到过\n    「显示导出完毕、下载列表里却没有文件」），点一下就能补存。同版还修了\n    「手动填角色 ID 时会漏掉那段没存档的对话」。\n  - **v1.15**：面具没导全时会明确告诉你少了几个，不再让你以为导全了。\n  - **v1.16**：打包时更省内存；一包特别大的时候会提前提醒你手机可能扛不住。\n  - **v1.17**：`.md` 加了 UTF-8 BOM，**修掉安卓上「有的文件正常、有的中文乱码」**。\n  - **v1.18**：导出期间请求「保持屏幕常亮」，减少手机上跑到一半被系统回收。\n  - **v1.19**：成批导时可以「**从第几个开始**」——中断后不用从头再来；\n    403 报错会说人话。\n  - **v1.20**：🔴 **修了一个真 bug**——某些角色名会被洗成同一个文件名，\n    导致「文件名是 A 卡、内容是 B 卡」。**有大量角色的建议升级后重导一次。**\n  - **v1.21**：新增「**酒馆对话（.jsonl）**」输出，可以把记录导进 SillyTavern。\n  - **v1.22**：一个文件都没产生时会**直接说明白**，不再照旧说「文件在下载目录里」；\n    网页阅读器的「隐藏我的发言」修好了（以前点了没反应）。\n  - **v1.23**：新增「**每包最多多少段对话**」——**对话上百段、以前一导就崩的角色现在能导了**。\n  - **v1.24**：没导完整的段会在结尾**逐条列出是哪个角色、哪一天**；\n    并且发现少拿到时会**自动换种翻页方式重试**，能多救回一类情况。\n  - **v1.25**：某个角色大到报 `Invalid string length` 时不再整轮失败——\n    完整备份会自动退让（去缩进 → 一段一个 JSON），报错也会告诉你该怎么办。\n  - **v1.26**：「没导完整」的提示改写——**条数对不上不一定是没抓到**，\n    也可能是 mufy 迁移丢过记录而总数没更新（已有用户查清一例）。\n  - **v1.28**：两件用户报上来的事——\n    **① 很久以前的存档导出来只有 1KB、里面只有几句话**，现在会明确标出来\n    并告诉你怎么救（去 mufy 里把那个存档「载入」再重导，就能拿到全文）；\n    **② 同一份聊天记录被导了两遍**（你载入过某个存档，它同时又成了「最后一次聊天」），\n    现在内容一字不差的两段会**自动合并成一份**，并在日志和目录里说清楚。\n  - **v1.29**：超大角色会**赶在浏览器杀掉整个标签页之前先停下来**，并直接告诉你\n    该把「每包最多多少段对话」填成几。以前是页面「啪」地变成一张白底报错页\n    （`Out of Memory`），日志和提示全没了，根本不知道该怎么办。\n  - **v1.30 \u002F v1.31**：**一条对话都取不到的角色，以前会被整个跳过，现在会出一个包**\n    （里面至少有开场白），并且**照实告诉你是怎么回事**——\n    🔴 特别是这种：**你明明聊过，但接口现在一条正文都给不出来**。\n    以前这种角色连个文件都没有，你根本不会发现它「不见了」。\n  - **v1.32**：**电子书改成从早到晚排**。以前书的第一章是你**最近**聊的那段，\n    翻开第一页就懵——有用户以为「最前面的聊天记录消失了」，其实它在最后一章。\n    现在第一章就是最早那段，从头读到尾就是时间顺序。\n    （ZIP 不变，仍是「最新的在前」：那是备份，查最近的最方便。）\n  - 🔴 **v1.33**：**一整段特别长（上千条）的对话，以前可能只导到一部分，而且一声不吭。**\n    接口自报的总数**本身就可能是被截过的**（有用户拿 mufy 官方导出对过账：\n    同一段官方那边 2971 条，接口却说只有 1000 条）——两个数一样，\n    旧版就以为拿全了，**连个警告都不会给**。现在遇到可疑的整数会**主动往后多翻几页**，\n    翻出来的会在日志里写「往后又翻出 N 条」。\n    **如果你有一整段上千条的对话，值得用这一版重导一次。**\n  - 🎯 **v1.34**：接着上面那条再试一发——**改成一次请求就要 2000 条**。\n    ⚠️ **已经实测过了：这一发也没能多拿到。** 在那位用户那段对话上，\n    我们试过的三种要法（`500×2 页` \u002F `从第 3 页往后要` \u002F `一次要 2000`）**都停在 1000**。\n    这一发留着不删（代价只有一次请求，且只落在可疑的段上），但**别指望它**。\n    **一整段上千条、又想要更早内容的，走 mufy 官方的引继码导出**（那是另一条路）。\n  - 🔴🔴 **v1.35（如果你有上千条的长对话，只升这一版就够）**：\n    **换掉了「翻完了没有」的判据。** 以前是「拿到的条数够了接口自报的总数就停」——\n    可那个总数会撒谎，于是同一个毛病换着长相咬了三次（说 1000 其实不止、\n    截在 1026 这种数上就漏掉……每修一次就再漏一种数字）。\n    现在**不看总数，只看这一页装满了没有**：满页就继续要下一页，\n    出现不满的一页才算到头。这个接口只有「第几页 \u002F 每页几条」两个旋钮，\n    「一直要到给不满为止」在道理上**就是穷尽**，不会再有下一种漏法。\n    **对普通对话反而更省**（25 条的段第一页就没装满，立刻停）；\n    只有长段会多问一页，而那一问正是关键的一问。\n    同版还加了**长段体检**：导出日志和 `00_目录.md` 里会写明\n    「接口说 N 条 \u002F 实际取到 M 条 \u002F 最早一条是哪天」，\n    **你自己就能判断有没有缺前面，不用再导第二遍来试。**\n  - **v1.36 \u002F v1.37**：面板上「输出方式」那四项**每项都配了一句人话**，选到哪个说哪个；\n    体量过大时的那段建议也改成**看人下菜**——\n    已经填过分批的不会再被劝\"填 20\"（那是往回走），\n    导电子书的也不会再被劝去关一个**在这条路上根本不存在**的 JSON 开关。\n  - （其余情况已经导好的文件不受影响，不用重导——除非你正被上面那个乱码问题困扰。）\n- **想导人设面具**：要，得到 **v1.11** 才有那一项。\n- **想导你自己写的角色卡**：要，得到 **v1.12** 才有那一项。\n\n怎么升，取决于你当初是怎么装的：\n\n- **点上面那个链接装的**（推荐的装法）：Tampermonkey 会自己检查更新，默认每天一次。\n  懒得等就手动催：点 Tampermonkey 图标 →「**管理面板**」→「**已安装脚本**」→\n  右上角「**检查更新**」。\n- **当初是自己复制粘贴装的**：**不会自动更新**，得再走一遍上面那个链接重装一次\n  （或者把旧脚本内容整个替换成新的）。\n- **iPhone \u002F iPad（Safari + Userscripts）**：**不会自动更新，但更新只要点两下**——\n  用 Safari 打开下面这个网址，页面上会出现一条\n  「**Userscript Installed: Tap to re-install**」，**点它**就覆盖成新版了。\n\n  \u003Chttps:\u002F\u002Fraw.githubusercontent.com\u002Fwillwefind\u002Fmufy-batch-export\u002Fmain\u002Fmufy-batch-export.user.js>\n\n  > 🚨 **点之前先把页面下拉刷新一下**（那个网址有几分钟缓存，不刷新可能装到的还是旧版）。\n  > 装完**回 mufy 那个标签页刷新一次**才生效 —— 和第一次装脚本时一样。\n  >\n  > 🔴 **如果你是 2026-08-10 凌晨装的 v1.33，面板上会写着 `v1.32`——那是我们的显示错误，\n  > 不是没装上。** 脚本本身就是新的（`@version` 是对的），只是面板标题里那个数字忘了跟着改。\n  > 已经修好了，**重新装一次**面板就会显示当前真实的版本号（现在是 `v1.37`）。\n  > 给踩到的人添麻烦了，抱歉。\n  >\n  > **装完版本号还是旧的？** 按这个顺序：\n  > ① 先**把 Safari 完全关掉重开**（从后台划掉，不是刷新页面）；\n  > ② 还不行就**把旧的那份删掉再装一次**——脚本是一个真实文件，\n  > 在你当初指定给 Userscripts 的那个文件夹里（「**文件**」App 里找），\n  > 删掉那个 `.user.js`，再回 Safari 打开上面的网址点横幅装。\n  >\n  > ⚠️ ᴀA 弹出的那个 Userscripts 面板**是用来开关脚本的，点进去不一定能编辑**——\n  > 点不开很正常，别在那儿较劲，走上面「文件」App 那条。\n\n装完在 Tampermonkey 面板里看一眼版本号是不是 **1.37.0**，或者打开导出面板，\n标题右边会写着 `v1.37`。\n\n### 3. 开始导出\n\n> ## 🚨 左下角没有出现按钮？先看这里\n>\n> **这是目前最多人卡住的一步，而且十有八九不是脚本的问题。**\n>\n> **Chrome 138 版本以后，浏览器默认不允许扩展运行用户脚本**——这个开关是**关着**的，\n> 装好 Tampermonkey、脚本也显示「已启用」，它依然一行都不会跑。\n> 点开 Tampermonkey 图标时，如果看到一句「**此脚本还未被执行**」，基本就是它。\n>\n> **打开它**（30 秒）：\n>\n> 1. 地址栏输入 `chrome:\u002F\u002Fextensions` 回车\n> 2. 找到 **Tampermonkey（篡改猴）**，点「**详细信息**」\n> 3. 往下找到「**允许用户脚本**」，**打开**\n> 4. 回到 mufy 页面**刷新一次**\n>\n> - **旧一点的 Chrome**：同一页右上角打开「**开发者模式**」。\n> - **Edge**：地址栏输 `edge:\u002F\u002Fextensions`，左下角「**开发人员模式**」；\n>   较新的 Edge 也改成了在扩展详情里开「**允许用户脚本**」，两处都看一眼。\n>\n> **📌 以前明明能用，最近突然没按钮了？** 多半也是这一项——\n> 浏览器大版本更新后这个开关可能被重置，脚本不会报错，就是安静地不跑了。\n>\n> ---\n>\n> **懒得折腾 \u002F 上面弄完还是没有？用这条，它绕开插件，一定能用：**\n>\n> 0. **先确认你在 mufy 里是登录状态**（能看到自己的角色列表）。没登录的话粘进去也只会\n>    提示「续不上登录态」。\n> 1. 在 mufy 的页面上按 **F12**\n> 2. 上面会出现一排标签：**欢迎 \u002F 元素 \u002F 控制台 \u002F 源代码**——点「**控制台**」\n>    （英文版叫 **Console**，就是同一个）\n> 3. 看最下面那一行，开头有个 **`>`**，**点一下它旁边的空白**，光标会在那儿闪\n> 4. 第一次用 Chrome 可能不让粘贴，要你先手打一句 `allow pasting` 回车（只需一次）\n> 5. 打开[脚本地址](https:\u002F\u002Fraw.githubusercontent.com\u002Fwillwefind\u002Fmufy-batch-export\u002Fmain\u002Fmufy-batch-export.user.js)\n>    → `Ctrl+A` 全选 → `Ctrl+C` 复制\n> 6. 回到刚才 `>` 那一行 → `Ctrl+V` 粘贴 → **回车**\n> 7. 左下角出现「⬇ 批量导出」按钮，用法完全一样\n>\n> 💡 控制台里本来就飘着一堆黄的红的（网页自己的报错），**不用管**；\n> 但如果满屏都是 **401**，说明你的登录过期了，先重新登录再来第 5 步。\n>\n> 代价只是**关掉标签页就没了**，下次再粘一遍。急着导的时候走这条最快。\n\n1. 打开 mufy，登录，随便进一个角色的聊天页\n2. 页面**左下角**会出现一个 **「⬇ 批量导出」** 按钮，点它\n3. 面板里选：\n   - **范围** → 想备份全部就选「全部聊过的角色」\n   - **输出方式** → 拿不准就用默认的「每段对话一个文件（打包成 ZIP）」（唯一带原始数据的）；\n     只想当小说读就选「**每个角色一本电子书（EPUB）**」。\n     四个选项的区别见下面「[「输出方式」那四个到底选哪个？](#输出方式那四个到底选哪个零基础版)」\n4. 点 **开始导出**，然后等着\n\n导出好的文件会自动下载到你浏览器的下载文件夹里，每个角色一个 `.zip`（或一本 `.epub`）。\n\n### 「输出方式」那四个到底选哪个？（零基础版）\n\n**先记一句：这四个只决定\"东西打包成什么样\"，不决定\"导多少\"。** 导多少是上面那个「范围」管的。\n**想要几种就跑几遍，互不影响，也不会覆盖。**\n\n**一句话对号入座：**\n\n| 你想干什么 | 选这个 |\n|---|---|\n| **把记录存起来，以后不怕丢** | **每段对话一个文件（ZIP）** ← 默认，拿不准就选它 |\n| **一口气从头读到尾** | 全部合并成一份 Markdown |\n| **当小说躺着读 \u002F 手机上读** | 每个角色一本电子书（EPUB） |\n| **搬去酒馆（SillyTavern）接着聊** | 酒馆对话（.jsonl） |\n\n---\n\n**① 每段对话一个文件（打包成 ZIP）** —— *默认，也是唯一算得上\"备份\"的那个*\n\n- **出来是什么**：每个角色一个压缩包。解开来：一段对话一个 `.md`、`00_开场白.md`、\n  `00_目录.md`（索引，能点进每一篇），还有 **`_原始数据.json`（一字不改的原文）**。\n- **用什么打开**：`.md` 用记事本 \u002F Markdown 阅读器都行；\n  电脑上直接把整个文件夹丢给[网页阅读器](#第二步之-a用网页阅读器翻看)，**不用解压**。\n- **谁该选它**：**所有人**。这是唯一保留原始数据的输出，别的都是\"给人看的成品\"。\n- **顺序**：**最新的在前**（备份是拿来查的，最近那段放最前面最方便）。\n\n**② 全部合并成一份 Markdown** —— *一个长文件，从头读到尾*\n\n- **出来是什么**：**一个角色一份 `.md`**（不是所有角色挤进一个文件），\n  开场白和每段对话依次接下来。\n- **和 ZIP 差在哪**：少了 `00_目录.md` 索引（合并版靠标题分节，用不着）。\n  ⚠️ 勾了「附带 JSON」的话，这条路是**另外单独下一个 `.json`**，不打包在一起，别以为漏了。\n- **谁该选它**：想一路滑到底通读、或者想丢进别的软件全文搜索的人。\n\n**③ 每个角色一本电子书（EPUB）** —— *成品书，最适合手机*\n\n- **出来是什么**：一个角色一本 `.epub`，自带封面和目录，一段对话一章，开场白单独一章。\n- **用什么打开**：微信读书 \u002F Apple Books \u002F 静读天下 \u002F 多看——翻页、书签、进度都是原生的。\n- **代价**：正文是**清理过**的（去掉 `\u003Cthink>`、状态栏 HTML、给模型看的规则行），\n  **不含原始数据**。所以：**想备份请另外再导一次 ZIP。**\n- **顺序**：**从早到晚**（书是从第一页读起的，第一章就是你最早聊的那段）。\n\n**④ 酒馆对话（.jsonl）** —— *只有要搬去酒馆才选*\n\n- **出来是什么**：一段存档一个 `.jsonl`，外加一份 `00_导入说明.md`。\n- **怎么用**：酒馆里建好这个角色的卡 → 选中它 → 对话列表 → **导入对话** → 选一个 `.jsonl`。\n- **⚠️ 不放开场白**：酒馆的第一条消息来自角色卡自己的开场白，这里再塞一条会重复。\n- **谁该选它**：**不打算搬去酒馆的人，完全用不上这个。**\n\n---\n\n📌 **两个最容易踩的误会：**\n\n1. **「全部合并」不是\"把所有东西合成一个文件\"** —— 它是**一个角色一份**；\n   而且**不包含**人设面具和你自己的角色卡（那是「范围」里另外的选项，要单独再导一次）。\n2. **ZIP 和 EPUB 的顺序是反的，这是故意的**：一个给你查（新→旧），一个给你读（早→晚）。\n   同一段对话在两边的「第 N 段」编号因此不一样，**别拿号码互相对，看日期最准**。\n\n> 💡 **拿不准就用默认的 ZIP 先导一份**（那是唯一有原始数据的），\n> 想读得舒服再单独跑一次 EPUB。两次互不影响。\n\n> **跑之前记得做这两件事，不然会白跑：**\n>\n> 1. 浏览器设置里把「**下载前询问每个文件的保存位置**」**关掉**\n>    （地址栏输 `chrome:\u002F\u002Fsettings\u002Fdownloads`）。不关的话，每个角色都会弹一次\n>    「另存为」窗口，几百个角色就是几百个窗口。\n> 2. **跑的时候别把这个标签页切到后台。** 浏览器会给后台标签页降速，导出会卡住。\n>\n> 中途浏览器会问一次「是否允许下载多个文件」，点**允许**。\n\n---\n\n## 第二步之 A：用网页阅读器翻看\n\n打开这个网页，点「选择存档文件夹」，选中放那些 zip 的文件夹：\n\n### 👉 \u003Chttps:\u002F\u002Fwillwefind.github.io\u002Fmufy-batch-export\u002Fmufy-reader.html>\n\n不用解压，它直接读 zip。左边是角色和章节，右边是正文。\n\n> 📱 **手机也能用，但请优先用「直接选 zip 文件（可多选）」那个按钮。**\n>\n> 用它可以**一次把所有角色的 zip 全选进来**，一步到位。\n> 上面那个「选择文件夹」在手机上**也点得动**（实测），只是手机的文件选择器\n> **一次只能挑一个**，几十上百个角色那样点会点到崩溃 —— 所以别走那条。\n>\n> （界面是按大屏排的，手机上会挤一点；想读得更舒服就用 EPUB。）\n\n- **分页读，不用一路往下滑**：长存档会切成一页页，`←` `→` 翻页；\n  底部那个页码是**可以直接填的**——162 页的存档想去第 80 页，填个数字回车就到（**新增**）；\n  右下角还有**一键回顶 \u002F 回底**两颗按钮（键盘 `Home` \u002F `End` 同样可以），\n  内容比一屏长才会出现（**新增**）；\n  翻到本段最后一页再按一下，就自然进入下一段（像翻书那样连着）。\n  想回到原来那种一路滚的读法，把「分页」改成「滚动」就行；页的长短也能调。\n- **会记住你读到哪**：下次打开同一个角色，直接回到上次那一段那一页。\n- **八套皮肤**：白 \u002F 豆沙绿 \u002F 羊皮纸 \u002F 冷灰蓝 \u002F 昼 \u002F 灰 \u002F 夜 \u002F 纯黑\n  （中间四套是按护眼调的：底色不用纯白、字色不用纯黑，明度差压在不刺眼的区间）。\n- **十种字体**，字号、行距、页宽都能调，设置会记住。\n  部分中文字体需要你自己系统里装了才会生效，没装就自动退到系统宋体，不影响阅读。\n- **隐藏我的发言**：RP 记录里你发的常常是 `$指令`，藏起来只剩角色的叙述，最像读小说\n  （⚠️ 这个按钮在旧版里点了没反应，**已修**——请重新下载一次阅读器网页）\n- **藏脚手架**：卡里给模型看的「规则：…」「待生成」这类行，读小说时是噪音，默认藏起来。\n  现在会在标题下写明**这一段藏了几行**——以前它在大多数角色身上什么都不做，\n  你根本没法判断它有没有在工作。\n- **只导入一次**：第一次选完文件夹后它会记住内容，以后打开直接就是完整书架\n\n> **你的存档不会上传到任何地方。** 这是个纯前端网页，文件全程只在你自己电脑上读。\n>\n> ⚠️ **别选云盘目录**（WPS 云盘 \u002F OneDrive）。云盘里的文件是「占位文件」，\n> 本地只有壳，浏览器读不到，会显示「一个 zip 都没有」。\n> **先把文件夹复制到本地硬盘**（比如 D 盘），再选那个副本。\n\n---\n\n## 第二步之 B：转成电子书，在手机上读\n\n### 最省事的做法：导出时直接选 EPUB\n\n**v1.10 起不需要 Python 了。** 在导出面板的「输出方式」里选\n「**每个角色一本电子书（EPUB）**」，导出来的直接就是书，每个角色一本，自带封面和目录。\n\n拿到 `.epub` 之后跳到下面的「传到手机」那一段就行。\n\n> 已经导过一堆 zip、不想重导的，用下面的 Python 脚本把它们就地转成书。\n\n\u003Cdetails>\n\u003Csummary>用 Python 脚本转已有的 zip（点开）\u003C\u002Fsummary>\n\n这一步需要在电脑上装 **Python**。\n\n### 1. 装 Python\n\n\u003Chttps:\u002F\u002Fwww.python.org\u002Fdownloads\u002F>\n\n下载安装时，**第一个页面底部的 `Add Python to PATH` 一定要勾上**，然后一路下一步。\n\n### 2. 下载这个仓库\n\n回到仓库首页，绿色的 **Code** 按钮 → **Download ZIP** → 解压到一个文件夹。\n\n### 3. 把 zip 放对位置\n\n在解压出来的文件夹里新建一个叫 **`存档`** 的文件夹，把第一步导出的所有 `.zip` 放进去。\n\n看起来应该是这样：\n\n```\n你解压出来的文件夹\u002F\n├── make-epub.py\n├── 存档\u002F\n│   ├── mufy_角色A_20260807-0324.zip\n│   ├── mufy_角色B_20260807-0324.zip\n│   └── ...\n```\n\n### 4. 运行\n\n在那个文件夹的**地址栏**里输入 `cmd` 按回车（会弹出一个黑色窗口），然后输入：\n\n```\npython make-epub.py\n```\n\n按回车，等它跑完。成品出现在旁边新出来的 `EPUB` 文件夹里，**每个角色一本书**。\n\n> 只想先试几本？用 `python make-epub.py --limit 3`\n\n### 🔗 分批导出的几十个包，怎么合成一本书\n\n对话上百段的角色要填「每包最多多少段」分批导，于是**一个角色出好几个包**\n（文件名带「第几到第几段」）。想通读的话——\n\n**把这个角色的所有分批 zip 都放进 `存档` 文件夹，跑一次 `python make-epub.py` 就行。**\n它会**自动认出它们是同一个角色的不同批次，按顺序接成一本完整的书**。\n\n- 认的不是文件名，是包里记着的「我是第几批 \u002F 一共该有几段」，所以**顺序不会乱**；\n- **少了哪一批它会当场喊出来**（写明少了几段），不会闷声出一本残书；\n- 开场白只在第一批里，合并后照样在书的最前面；\n- 想回到旧行为（一个包一本）就加 `--no-merge`。\n\n> ⚠️ 这条只对 **zip** 有效。**已经导成 `.epub` 的分批书没法合并**——\n> EPUB 是成品书，原始数据不在里面。这种情况只能重导一次 ZIP（或者干脆不分批重导）。\n\n> 💡 **其实多数人不用分批**：那个格子是给「内存不够、一导就崩」准备的。\n> 电脑上导通常留空就行，直接出一本完整的书。\n> 真的导不动，先试**取消勾选「附带 JSON 完整备份」**（占一半以上体积），再考虑分批。\n\n\u003C\u002Fdetails>\n\n### 传到手机\n\n把 `.epub` 文件传到手机（微信传给自己、网盘、数据线都行），然后：\n\n- **微信读书**：电脑上打开 \u003Chttps:\u002F\u002Fweread.qq.com\u002F> → 「传书到手机」→ 拖进去\n- **Apple Books \u002F 静读天下 \u002F 多看**：直接用「用其他应用打开」选它\n\n翻页、目录、书签、进度都是原生的，和读正经电子书一样。\n\n---\n\n## 导出的东西长什么样\n\n每个角色一个 zip，解开来是这样：\n\n```\n00_开场白.md                                   ← 角色卡自带的开场白\n00_目录.md                                     ← 索引，可点进每一篇\n01_20260806-2352_闷热湿黏的梅雨夜 · 宴会厅.md\n02_20260531-0237_我给这段存档写的备注.md          ← 你写过备注的，用你的备注\n03_20260531-0101_未存档_沉闷微雨的夏夜.md        ← 你没按过保存的那段\n_原始数据.json                                  ← 完整原文备份\n```\n\n文件名是 `序号_日期_线索`。你写过备注的用备注；没写的自动取那段开场白的场景抬头。\n每个文件的修改时间也是对应日期，资源管理器里能按时间排。\n\n---\n\n## 顺带：把人设面具也导出来\n\n面具是账号级的一份清单，不挂在任何角色底下，所以走单独一条路：\n面板里 **范围** 选「**人设面具（全部）**」，其余不用管，点开始导出。\n\n一个面具一份 md，按面具编辑框里的六栏原样分节：\n\n```markdown\n# 我给这个面具写的备注\n\n- 面具 ID：12345678\n- 创建时间：2026-01-02 15:04:05\n- 导出时间：2026-08-07 23:01:02\n\n---\n\n## 备注\n## 名称\n## 性别\n## 我的描述\n## 我的喜好\n## 指令\n```\n\n六栏一栏不落，空的也留着写「（空）」——空着也是事实，删了以后就看不出原来有没有。\n一次性打包成 `mufy_人设面具_N个_日期.zip`，里面还有 `00_目录.md` 和\n`_原始数据.json`（接口原样返回，一字不改）。想一口气通读就把输出方式改成\n「全部合并成一份 Markdown」。\n\n> 「清理 think」对面具没有作用（面具本来就是纯文本设定），\n> 「EPUB」对面具也无从谈起（没有对话可成章）——选了面具之后面板会自己把它们说明白。\n\n### ⚠️ 没订阅的账号，只能导出 mufy 还让你看见的那几个\n\n有用户实测：**未订阅的账号，面具只导得出现有的那几个，被隐藏的那些拿不到。**\n\n这不是脚本少翻了页——**接口本身就只返回你当前有权看到的面具**，脚本没有办法绕过。\n（mufy 的会员权益里包含「无限人设面具」，退订之后超出额度的那些会被隐藏起来。）\n\n**v1.15 起脚本会把这件事直说**：如果接口报的总数比实际拿到的多，日志里会出现一行红字，\n**导出包的 `00_目录.md` 开头也会写一句**，告诉你少了几个。不会让你以为导全了。\n\n> 💡 **所以面具要趁还看得见的时候导。**\n>\n> ⚠️ 但**别把这条推广到聊天记录上**——那是两回事，见下面一节。\n\n---\n\n## 你自己写的角色卡\n\n**范围**选「**我创建的角色卡（全部）**」。一张卡一个文件夹：\n\n```\n00_目录.md\n01_角色名\u002F\n   卡片.md      ← 全字段明文，分好节\n   卡片.json    ← 接口原样返回，一字不改\n   头像.jpg     ← 图是真下下来的，不是链接\n   封面.jpg\n02_另一个角色\u002F\n   ...\n```\n\n`卡片.md` 里按你在创建页看到的栏目分节：**角色介绍 \u002F 人设 \u002F 逆境处理 \u002F 开场设计 \u002F\n小剧场 \u002F 全局美化 \u002F 情节设定 \u002F 输出设定 \u002F 样例对话与文风 \u002F 资料库 \u002F 物品栏 \u002F\n默认认知 \u002F 厨子の厨艺分享 \u002F 正则条目**（正则一条一小节，匹配和替换各自成块）。\n空的栏也留着写「（空）」。\n\n### 官方已经有「导出引继码」了，为什么还要这个\n\n因为那份 XML **不是存档，是搬家包**。在一个有 4 张自制卡的真实账号上逐字段比对过\n（SHA-256，不是肉眼看）：\n\n| | 官方 XML 里 |\n|---|---|\n| 人设 \u002F 开场 \u002F 输出设定 \u002F 样例对话与文风 \u002F 情节设定 \u002F 作者的话 \u002F 元信息 \u002F **正则条目** | ✅ 明文，与接口**逐字一致** |\n| **小剧场、全局美化** | 🔒 **加密**（base64 解开是 `{salt, iv, ciphertext}`） |\n| 角色图片 | ⚠️ 只有一条链接，图不在文件里 |\n\n也就是说：官方那份正文相当老实，**但你最花心血的美化代码在里面是密文**——\n那两块往往是整张卡里最长的部分，都是卡主自己一个字一个字写的，\n却在自己的导出文件里读不出来。图片也只是链接，哪天号没了或者站没了，图跟着没。\n\n**这个工具不碰那套加密，也不需要碰**——接口本身返回的就是明文，直接落地即可。\n它做的就两件事：把全部字段按人能读的样子写下来，把图真下下来。\n\n> 想再拿一份官方引继码用来搬家，照旧去创建页导，两者不冲突。\n\n---\n\n## 导进酒馆（SillyTavern \u002F Tavo 之类）\n\n输出方式选「**酒馆对话（.jsonl，一段存档一个文件）**」，\n出来的 ZIP 里一段存档一个 `.jsonl`，外加一份 `00_导入说明.md`。\n\n导法：在酒馆里建好这个角色的卡 → 选中它 → 对话列表 → **导入对话** → 选一个 `.jsonl`。\n一个角色可以挂多个对话，想导几段就导几段。\n\n### 能从以前的记录接着聊吗？能，但要先知道三件事\n\n**一、文字肯定接得上。** 导进去就能看到全部历史，直接往下打字，酒馆会接着往下写。\n\n**二、模型只看得到最近的一段。** 酒馆会把最近能塞进上下文的消息发给模型，\n更早的对你是存档、对它不是记忆。**这点 mufy 也一样**（所以才有「保存并开启新对话」）。\n想让它记住早期的关键设定，用酒馆的**总结 \u002F 作者注释 \u002F 世界书**把它们沉淀下来。\n\n**三、角色不会一模一样。** mufy 里那个语气，是人设＋小剧场＋输出设定＋正则\n再加上 mufy 那边的模型一起长出来的。换到酒馆，模型和提示词拼装方式都变了，\n**就算人设一字不差贴过去，口吻也会变**。\n导入历史其实是最有效的\"定调\"手段（模型会照着已有对话模仿），但它是像，不是同一个。\n\n### 什么搬得过去，什么搬不过去\n\n| | |\n|---|---|\n| 聊天记录 | ✅ 就是这个功能 |\n| 人设 \u002F 开场 \u002F 输出设定 \u002F 样例对话 | ✅ 用「我创建的角色卡」导出的 `卡片.md`，照着重建卡片 |\n| 正则条目 | 🟡 酒馆有 Regex 扩展、也是 JS 正则，能手工搬；但作用域字段两边对不上，要逐条判断 |\n| **小剧场 \u002F 全局美化** | ❌ 那是 mufy 的网页渲染层，酒馆没有对应物 |\n\n> **没有放开场白**：酒馆的第一条消息来自角色卡自己的开场白，这里再塞一条会重复。\n> 开场白原文在 ZIP 输出里（`00_开场白.md`）。\n\n> ✅ **SillyTavern 导入已实测走通**：真机导入后，条数对、说话人不反、\n> **开场白一次都没重复出现**，可以接着往下聊。\n>\n> ⚠️ **手机上的 Tavo 等前端**：它们的**角色卡**兼容 SillyTavern 规格，\n> 但对话能不能直接吃这个 `.jsonl`，**没有实测过**，请自己试一下。\n\n> 💡 **用 `\u003Cdetails>` 搭的状态栏会被保留**，而且在酒馆里会渲染成可折叠的块。\n> 「清理 think \u002F 状态栏 HTML」清掉的是 `\u003Cthink>`、注释、`\u003Cstyle>`／`\u003Cscript>`\n> 以及 `div` `span` `p` `table` 这类标签；**`\u003Cdetails>` \u002F `\u003Csummary>` 不在清理名单里**\n> —— 实测下来这样反而更好看，就没动它。\n\n---\n\n## 聊天记录不受这个限制（连\"已经找不到的角色\"都导得出来）\n\n上面说的面具限制**只适用于面具那种「按会员额度限量的功能」**。聊天记录是另一回事：\n\n有用户反馈，用这个工具导出了**自己很久以前聊的第一个角色**——那个角色在 mufy 里\n她已经找不到了。这不是意外，是接口结构决定的：\n\n- **角色列表走的是「你自己的互动历史」**。`\u002Fapi\u002Fcharacters\u002Fquery_session` 一共就\n  9 个字段（`characterId` \u002F `lastInteracted` \u002F `lastSessionId` \u002F `lastDialogContent` 等），\n  **一个「可见性 \u002F 已删除 \u002F 状态」字段都没有**。它列的是\"你跟谁聊过\"，\n  不是\"现在还能搜到哪些角色\"。所以作者把卡下架或删掉，它照样在你的列表里。\n- **对话正文挂在你自己的 session 底下**，按 `sessionId + characterId` 取，是你的数据。\n- **脚本会一路翻到底**。mufy 的界面通常只让你看到最近那一截，翻不回三年前；\n  脚本把每一页都翻完（实测某账号 211 个聊过的角色全在）。\n- **就算角色卡本身已经取不到了**，脚本会退回用角色 ID 的前 8 位当名字**继续导对话**，\n  一条都不会少——只是文件名会变成一串字符而不是角色名。\n\n> ✅ **这条不是推演，是撞上过**：在一个真实账号上导全量时，有两个角色的压缩包\n> 名字变成了一串字符；拿去 mufy 上核对，**那两张卡确实已经被下架了**。\n> 而它们的**聊天记录一条不少地导了出来**。\n> （所以看到这种文件名不用慌，它恰恰说明脚本救回了一个你已经找不到的角色。）\n\n> 一句话：**「现在还能不能搜到这个角色」不影响导出**——列表按你的互动历史来。\n\n### ⚠️ 但「存档看不看得见」是另一回事\n\n上面说的是**角色**。**存档**要分开讲，这两件事很容易混：\n\n| | |\n|---|---|\n| 角色在 mufy 里搜不到了 \u002F 被下架删卡 | ✅ **照样能导**，列表按「你跟谁聊过」来 |\n| 聊过但**从没按过保存**的最后一段 | ✅ **能导**（这是脚本特意补的，文件名带 `未存档_`） |\n| **历史存档过期了、界面上已经看不到** | ❌ **导不出来** |\n\n**为什么导不出**：脚本拿的是 mufy 自己那个「存档列表」接口，\n**它只返回你账号当前有权看到的存档**。界面上你看不到的，接口也不会给，脚本没有办法绕过。\n没有会员时超期的存档就属于这一类。\n\n多位用户实测过同一个结论：**还能看到的（包括还没过期的历史存档）都导得出来，\n已经看不见的导不出来。** 这不是脚本坏了，是数据那边就没给。\n\n> 💡 **所以：想留住的对话，趁还看得见的时候导。**\n> 在 mufy 里按一下「保存并开启新对话」也能让那一段更稳。\n\n> **v1.22 起，如果一轮跑完一个文件都没产生，面板会直接说明白**\n> （而不是照旧说一句「文件在下载目录里」让你去下载夹里空找）。\n\n（当然，这说的是 mufy 现在的行为。真正想留住的东西，导出来放在自己硬盘上才算数。）\n\n---\n\n## ⚠️ 最重要的一件事：你现有的备份可能是缺的\n\n如果你已经用别的办法导过 mufy，**很可能少了两样东西**。\n\nmufy 的「存档」是你按了「保存并开启新对话」才产生的。只顺着存档列表导，会漏掉：\n\n**一、你聊过但从没按保存的对话。**\n实测在一个 200 多角色的账号上：102 个角色一条存档都没有，\n但里面躺着 **1356 条消息**（最长的一个 112 条）。而且有存档的角色也照样漏——\n抽查 25 个，其中 24 个的最后一段没进过存档，又是 706 条。\n\n**二、角色卡自带的开场白。**\n它不在对话记录里，是挂在角色卡上的独立字段，实测一个角色的开场白有 1400 多字。\n每个角色都有，一个都跑不掉。\n\n> **v1.30 起，一条对话都取不到的角色也会出一个包**（里面至少有 `00_开场白.md`）。\n> 以前这类角色会被当成「没有可导出的对话」**整个跳过，连个文件都没有**——\n> 于是你根本不会发现它不见了。\n>\n> 🔴 **v1.31 又补了很重要的一层：说清楚到底是哪种情况。**\n> 有一种角色**你明明聊过，但接口现在一条正文都给不出来**（`total` 直接是 0、\n> 也没有任何存档）。实测遇到过：mufy 那边还记着「最后互动是四月某天」，\n> 内容却已经没了。\n> 这种包的 `00_目录.md` 里会写明**最后互动是哪天**，并让你去 mufy 打开看一眼自己判断：\n> 那边也是空的 ＝ 记录确实没了；那边还看得到 ＝ 是我们的问题，请报给我们。\n>\n> **绝不会再把这种情况写成「你没聊过」**——数据上它俩长得一样，但对人来说完全是两件事。\n>\n> （唯一例外是「酒馆对话」那种输出：它本来就不放开场白，所以没有对话＝真没东西可导，\n> 面板会照实说跳过。）\n\n这两样这个工具都会导出来（没存档的那段文件名带 `未存档_`，开场白是 `00_开场白.md`）。\n**我前两版都漏了，跑完还以为导全了。**\n\n> 顺带一提：脚本能捞的是「最后聊的那段」。一个角色如果有**好几段**都没存过档，\n> 更早的那些谁也够不着。**真正想留住的对话，还是在 mufy 里按一下\n> 「保存并开启新对话」最稳。**\n\n---\n\n## 常见问题\n\n**Q：mufy 页面左下角根本没出现那个按钮？**\n\n八成是浏览器没允许扩展运行用户脚本——Chrome \u002F Edge 默认是关的。\n`chrome:\u002F\u002Fextensions` → Tampermonkey →「详细信息」→ 打开「**允许用户脚本**」\n（旧版 Chrome 是右上角的「开发者模式」，Edge 是「开发人员模式」）。\n开完刷新 mufy 页面。脚本装没装好在 Tampermonkey 面板里能看见，\n但那个开关是关的话，装好了也不会跑。\n\n**怎么确认就是它**：点浏览器右上角的 Tampermonkey 图标，\n如果那里写着「**此脚本还未被执行**」，就是这个开关没开\n（它列的另外两个原因——脚本被禁用、URL 不匹配——都可以先不管：\n脚本在面板里显示「已启用」就没被禁用；`@match` 覆盖 mufy 的所有页面，\n在 `\u002Fexplore`、`\u002Fchat` 上都一样，实测过）。\n\n**急着用就走控制台那条**：在 mufy 页面按 F12 →\n点「**控制台**」那个标签（英文版叫 Console）→ 点最下面 `>` 那一行 →\n（必要时先手打 `allow pasting` 回车）→\n把[脚本](https:\u002F\u002Fraw.githubusercontent.com\u002Fwillwefind\u002Fmufy-batch-export\u002Fmain\u002Fmufy-batch-export.user.js)\n整段粘进去回车，按钮立刻出现，功能一模一样，只是关掉标签页就没了。\n详细分步见上面「3. 开始导出」那个 🚨 框。\n\n**Q：点安装链接一直显示「无法访问此页面 \u002F 检查是否有拼写错误」，篡改猴说「没有访问此页面的权限」？**\n\n**网址没打错。** 那个错误码（`DNS_PROBE_FINISHED_NXDOMAIN`）是**域名解析失败**——\n你的网络连不上 `raw.githubusercontent.com`。它和 `github.com` 是两个不同的域名，\n**经常一个通一个不通**，所以你能打开仓库首页、却打不开那个安装链接。\n\n篡改猴那句「没有访问此页面的权限」是连带的：当前页是个错误页，本来就没有脚本可装。\n\n**解法**：从 GitHub 的文件页**直接复制代码**，绕开那个域名——\n详细六步写在上面「[2. 装脚本](#2-装脚本)」那一节的 🌏 框里。\n（关键一点：点**复制图标**，别点 Raw 或 Download，那两个还是会跳去打不开的域名。）\n\n**Q：iPhone \u002F iPad 上我平常用的是 Chrome（或 Edge、夸克、QQ 浏览器），能装吗？**\n\n**不能——iPhone 上只有 Safari 跑得了用户脚本。** iOS 版的 Chrome 不支持扩展 \u002F\n用户脚本（篡改猴没有 iOS Chrome 版），而且它也没有电脑上那条「F12 控制台粘一次」的兜底。\n所以在 iPhone 上只有两条路：\n\n- **A：换 Safari** —— App Store 装免费的 **Userscripts**，照下面「[附：手机上全程走完](#附手机上全程走完iphone--安卓两边都有人走通)」那一节走，全程手机就能闭环。\n- **B：用电脑导一次** —— 最省事，手机只负责读电子书。\n\n⚠️ **换到 Safari 之后，记得在 Safari 里重新登录一次 mufy。**\n脚本用的是**你当前这个浏览器里的登录态**，Chrome 里登过不算数。\n（用谷歌账号还是邮箱登**都一样**，登录方式跟脚本没有关系。\n如果你说的\"用谷歌打开 mufy\"本来就是指\"用谷歌账号登录\"，那更简单：跟这一条无关，\n你只要人在 Safari 里就行。）\n\n📁 Safari 导出来的文件在「**文件**」App →「**我的 iPhone \u002F 下载项**」。\n\n**Q：iPhone \u002F iPad 上（Safari + Userscripts）左下角没有按钮？\n（或者面板里写着 `No matched userscripts`）**\n\nSafari 上不用篡改猴，卡点也和电脑那套不一样。已确认的三个原因：\n\n1. 🚨 **装完脚本之后，你没刷新那个页面。** 最常见的一个，也最容易被跳过——\n   **脚本只在页面加载的那一刻注入**，你装脚本时开着的那个 mufy 标签页是\"装之前\"的，\n   它不会自己变出按钮来。**回到 mufy 那个标签页刷新一次**（下拉刷新或点地址栏重新进），\n   按钮就出来了。**已有 iPhone 用户就卡在这一步**，面板当时显示的正是 `No matched userscripts`。\n2. 🚨 **你开着「无痕浏览」。** 这个最迷惑人——脚本装得好好的、Userscripts 面板里\n   看得见而且是启用状态，**就是不出按钮**。换普通标签页（必要时把 Safari 完全关掉重开）。\n   **已有用户就是这样，重开之后立刻就好了。**\n3. **网站权限只给了「允许一次」。** 换成「**始终允许**」，然后**刷新页面**。\n\n先排除脚本自身的问题：ᴀA → Userscripts 打开面板，**右上角总开关要是开的**，\n列表里「Mufy 批量导出聊天记录」要是**亮白色**（灰色 = 被停用）。\n这两样对了就说明脚本没毛病，往上看那两条。\n\n⚠️ **iPhone 上没有「F12 控制台」那条兜底**（那是电脑浏览器才有的）。\nSafari 这条实在不行，最省事是**用电脑导一次**，手机只负责读电子书。\n\n**Q：以前一直好好的，最近突然没有按钮了？**\n\n同上那个开关。**浏览器大版本更新之后它可能被重置**，而且失败得很安静——\n脚本不报错、Tampermonkey 里也照样显示「已启用」，就是不跑。\n先去 `chrome:\u002F\u002Fextensions` → Tampermonkey →「详细信息」看一眼「允许用户脚本」。\n\n**Q：装这个脚本会不会被封号？（有人遇到「Microsoft 帐户已锁定」）**\n\n> ✅ **先给结论：那一例已经查清楚了，不是封号。** 是微软的风控锁定，\n> **点一下「下一步」做个人机验证就解开了**，跟这个脚本没有关系（原因是挂着加速器）。\n> 细节在下面 📌 那一段。\n\n先把两件事分开，它们经常被混在一起。\n\n**① 你的微软 \u002F 谷歌账号：装脚本不会导致它被封。**\n\n装扩展、装用户脚本都是**你自己浏览器里的本地行为**——微软和谷歌的服务器收不到这个信号，\n它们不知道你在哪个网站跑了什么脚本。反过来，mufy 也没有任何渠道去封你的微软或谷歌账号，\n它能封的只有它自己这边的账号。\n\n> 📌 **真实的一例（2026-08-09）：看着像封号，其实是一步就能解开的验证**\n>\n> 一位安卓用户来问：「我想问问安卓手机到安装完脚本进mufy，\n> 它检测到违反了协议给我 Microsoft 账号封了怎么办？」\n>\n> 拿到截图之后看明白了：那是微软的 **「帐户已锁定」** 页（`account.live.com`），\n> 写着「我们检测到违反 **Microsoft 服务协议** 的活动，并且锁定了你的帐户。\n> **你只需在下一步中完成人机验证。**」\n>\n> **不是封号，是微软的风控锁定，点「下一步」过一次人机验证就能解开**，\n> 用不着申诉，也不用等。\n>\n> 两个最容易看错的地方：\n>\n> - 那句「检测到违反了协议」**是微软说的，说的是微软自己的服务协议**，\n>   不是 mufy 说你违反了 mufy 的协议——mufy 也没有权限去锁一个微软账号。\n> - **原因是加速器**，这位用户自己找到的：他上浏览器和 mufy 时一直挂着加速器。\n>   挂代理上网时微软账号还登着，是触发这种锁定最常见的情形（微软看到一个陌生的、\n>   很多人共用的 IP 在登你的账号）。\n>\n> **解锁之前先把加速器关掉**，用你平常那条网络去做人机验证，否则容易解开又被锁。\n> 想少挨这一下：用一个不登微软账号的浏览器去开 mufy，或者给账号补一个手机验证方式。\n>\n> 万一遇到的是真的登不回去（不是这种一步可解的锁定），入口也在微软那边：\n> 账户恢复表单 \u003Chttps:\u002F\u002Faccount.live.com\u002Facsr>。**mufy 和这个工具都插不上手。**\n\n**② 你的 mufy 账号：不能替它打包票，但到目前为止没有人报告过。**\n\n脚本用的是你**已经登录**的身份，调的是 mufy 网页自己就在调的那几个接口\n（就是你在页面里往上翻聊天记录时会发出的那些请求），只读**你自己账号里**的东西，\n**全程只读、不写**，请求之间留了 120–300ms 间隔、撞上限流会退避重试。\n到现在为止，服务器那边唯一出现过的反应是**临时 429 限流**\n（见下面那条，等一会儿自己就好，不伤记录、也不是封号）。\n\n但 mufy 的用户协议怎么判是他们说了算，我不能替他们保证。不放心的话：少量分批导、\n别开着加速器导、导完就把脚本关掉；或者干脆用 mufy 官方的引继码导出\n（正文是全的，代价是小剧场和全局美化那部分是加密的、图片只有链接）。\n\n**怎么分清被封的到底是哪个账号**：打开 outlook.com \u002F gmail 看能不能正常收信。\n**收得到** → 是 mufy 那边（走 mufy 客服申诉）；**收不到** → 是邮箱账号那边，跟 mufy 无关。\n\n**Q：那个「⬇ 批量导出」悬浮按钮挡住了 mufy 的按键，怎么办？**\n更新到 **v1.9**。手机／窄屏下按钮会自动抬到底部导航上方，不再压住首页键。\n按钮右上角有个 **✕**，点一下当次收起（刷新页面就回来）。\n\n**Q：怎么彻底关掉这个脚本？**\n点浏览器右上角的 **Tampermonkey 图标**，把「Mufy 批量导出聊天记录」的开关关掉就行。\n想再用的时候打开开关、刷新页面。\n（如果你是用控制台粘贴的方式装的，关掉标签页就没了。）\n\n**Q：我有一段对话上万轮，这工具扛得住吗？**\n扛得住。合成了一段 **1 万轮 \u002F 2 万条消息** 的对话做过全链路实测：\n导出 40 次请求全部抓到、0 重复 0 遗漏；转成的 EPUB 导进微信读书能正常打开和跳目录；\n用网页阅读器打开那一章也不卡。**不需要你做任何特殊处理。**\n\n**Q：手机上点 `make-epub.py` \u002F `mufy-reader.html` 只看到一堆代码？**\n正常，它们是代码文件不是 App。`make-epub.py` 要电脑上的 Python。\n**网页阅读器手机上能用**——用「直接选 zip 文件」那个按钮，可以一次多选整包\n（「选择文件夹」在手机上一次只挑得了一个文件，别走那条）。\n**导出和转电子书现在手机上也能做**，见下面的手机教程。\n\n**Q：手机上能全程走完吗？**\n能，两个平台都有人走通了。**iPhone**（Safari + Userscripts）已实测走完全程：\n装脚本 → 导出 → 出 EPUB → 微信读书打开。**安卓**用自带脚本功能的浏览器\n（X浏览器 \u002F Via）或火狐 + Tampermonkey，**已有安卓用户照最后一节的教程走通**。\n> 「网页阅读器」手机上也能用，**用「直接选 zip 文件」那个按钮、一次多选整包**\n> （「选择文件夹」在手机上一次只挑得了一个文件，几十个角色会点到崩溃）。\n> 界面按大屏排的，手机上会挤一点；想读得舒服还是 EPUB，本来也更像读书。\n\n**Q：点仓库里的 html 链接为什么显示的是代码？**\nGitHub 的 raw 地址会把网页文件当纯文本发，电脑手机都一样。\n要用阅读器请点上面那个 **github.io** 的地址；想下载文件就点文件页右上角的\n**Download raw file**。\n\n**Q：某个角色报 `Invalid string length`，整个导出失败、面板里连下载链接都没有？**\n\n**这不是网络问题，也不是内存慢慢耗尽**——是这个角色大到让脚本拼出了一个\n**超过 JS 语言上限的字符串**（引擎大约到 5 亿字符就直接报这个错）。\n最容易撞上限的是 `_原始数据.json`：它把整个角色序列化成**一个**字符串，缩进还让体积接近翻倍。\n\n**怎么办**（按顺序）：\n\n1. **面板上「每包最多多少段对话」填 20**，再导一次。分批之后每一批都远在上限以下。\n2. 还不行填 **10**。\n3. 或者先**取消勾选「附带 JSON 完整备份」**，只要 Markdown。\n\n**v1.25 起脚本自己也会退让**：那份完整备份太大时，先去掉缩进重试；还不行就\n**改成一段一个 JSON 文件**放进 `_原始数据\u002F` 文件夹里——Markdown 正文一篇都不会少。\n报错时面板也会直接告诉你上面这几步，而不是只甩一句英文。\n\n**Q：电子书导出成功了，但导进微信读书时卡在某个百分比失败？**\n\n多半是**某一章太大**（这个角色的单段对话特别长）。同样用「**每包最多多少段对话**」\n分批导 —— 分批模式下 EPUB 也会跟着分成几本小书，每本都好啃得多。\n\n**Q：整个页面崩了，显示「此页存在问题 \u002F 错误代码：Out of Memory」？**\n\n**这跟下面那条是同一个病，但要单独说一句：这个页面是浏览器弹的，不是脚本弹的。**\n整个标签页的进程被系统杀掉了，所以脚本的日志、面板、连它本来想告诉你的\n「内存不够，请填分批」那句话，全都跟着没了——你只看到一个白页。\n\n**照下面那条做（填「每包最多多少段对话」）就行**，只是别指望脚本会先提醒你。\n\n**v1.29 起脚本会赶在浏览器动手之前先停下来**：一批攥了太多字就主动报错、\n并直接告诉你该填多少，至少日志还在、别的角色还能接着导。\n\n**Q：对话特别多的角色导不出来，报 out of memory \u002F 页面直接崩了？**\n\n**填「每包最多多少段对话」，这是最有效的一招。** 面板上那个输入框，填 **20** 试试。\n\n> **每轮都粘了很长的长期记忆／世界书的，20 还不够，填 5 甚至 2。**\n> 决定成败的**不是段数，是总字数**。有用户一万轮、178 段，而且**每一轮都手工粘了\n> 几万字的长期记忆**——这种一段就顶别人几十段，卡在第 40 段左右整个页面就崩了。\n> （和长期记忆是什么格式无关：HTML 也好、纯文本也好，脚本只是原样搬运，\n> 不解析、不渲染，**只有体量本身要紧**。）\n\n为什么有用：以前是**把这个角色所有段的对话全抓进内存、再打成一个包**。\n上百段、每轮还带着长期记忆的角色，光这一步就能把浏览器撑爆\n（有人一万轮 \u002F 178 段，电脑上都 out of memory；也有人 iPad 上 170 档约 500MB 直接崩）。\n\n填了之后改成**一批一批地抓、抓完打包就放掉**，内存峰值只跟一批有关，和总量无关。\n代价是同一个角色会出好几个包，文件名带「第几到第几段」，放同一个文件夹里就是完整的。\n\n> **分批和不分批导出来的内容完全一样**——这不是估计：拿一个 53 段的真实角色两种模式各导一次，\n> 篇目数、文件名、每一篇的正文**逐字比对 0 处差异**，总字数都是 1,744,509。\n> 段号也是跨批连续的（01…53），不会因为分批而错乱。\n\n**这一招治不了什么**（两条，都是用户真撞上的）：\n\n- **切不开\"一整段特别长\"。** 那个格子切的是**段数**，不是段里的条数。\n  一个角色要是本来就只有一两段、而那一段有上千条，**填 1 也已经到底了**，\n  再调小没有意义。这种只能**用电脑导**（桌面浏览器的内存额度宽得多）。\n- **导电子书时，取消勾选「附带 JSON 完整备份」是没用的** ——\n  EPUB 那条路本来就不产出 JSON。（v1.37 起提示语会自己认这一点，不再瞎劝。）\n- mufy 那边看不到的存档（见上面那条）——那是数据就没有，不是内存问题。\n\n**Q：脚本说\"已导出\"，下载列表里却找不到文件？**\n\n**v1.14 起面板底部会留一排「⬇ 手动保存」链接**（最近生成的几个文件），\n直接点那个链接就能把文件存下来——手动点属于用户操作，浏览器基本不会拦。\n\n顺便按这个顺序查一下是哪一环：\n\n1. **日志里有没有 `⬇ 文件名 大小` 这一行？**\n   有 = 文件已经做好了，是浏览器没收下（往下看第 2、3 条）；\n   没有 = 没走到下载那步，日志里应该有别的提示。\n2. **地址栏最右边有没有一个\"下载被阻止\"的小图标？** 这个提示很容易被忽略。\n   点它选允许，或去 `chrome:\u002F\u002Fsettings\u002Fcontent\u002FautomaticDownloads` 把 mufy 加进允许列表。\n3. **下载目录还在吗？** 如果之前设成了外置存储 \u002F 云盘目录而现在不可用，\n   下载会失败得很安静。换回默认目录再试。\n\n> 早期版本（v1.13 及以前）在下载后 8 秒就注销 blob 链接，文件大或者机器慢的时候\n> 有可能让下载失败。v1.14 去掉了这个定时注销。\n\n**Q：导完之后页面自己刷新了一下，然后没有文件？**\n\n**那不是刷新，是这个标签页被系统回收后重载了**——多半是内存不够。\n一个存档特别多的角色（有人遇到过 352 段）打包时要在内存里同时放下正文、\n压缩产物和那份 JSON，手机浏览器（Safari 尤其）很容易顶不住。\n页面一重载，生成好的文件跟着没，连「⬇ 手动保存」也救不回来。\n\n三个办法，从省事到彻底：\n\n1. **取消勾选「附带 JSON 完整备份」**再导一次。那份通常占一半以上体量。\n2. **换成「每个角色一本电子书（EPUB）」**，正文清理过，比 ZIP 小不少。\n3. **用电脑导这个角色。** 桌面浏览器的内存额度宽得多，这是最稳的。\n\n**v1.16 起，体量特别大的时候面板会提前提醒你**，不用等它崩了才知道。\n\n**Q：导出来的文件，有的正常有的是乱码？（安卓上常见）**\n\n**不是文件坏了，是看它的那个 App 猜错了编码。**\n\n导出的 `.md` 是 UTF-8。安卓上不少文本 \u002F Markdown 阅读器**会自己猜编码**，\n猜成 GBK 的话中文就全成乱码。猜得准不准跟文件内容有关，\n所以会出现「同一批导出，有的正常有的乱码」这种怪事。\n\n**v1.17 起，所有 `.md` 都带上了 UTF-8 BOM**（一个看不见的标记，明着告诉阅读器别猜）。\n更新到 v1.17 重导一次就好了。\n\n已经导出来的旧文件也能救，不用重导：换个能手动指定编码的 App 打开，\n把编码设成 **UTF-8** 就正常了（比如 QuickEdit、Markor、或者电脑上的记事本 \u002F VS Code）。\n\n> `.json` 和 EPUB **故意没加** BOM——JSON 带 BOM 会让程序解析直接报错，\n> 电子书阅读器也不需要。\n\n**Q：手机上导「全部角色」，息屏几次就被踢出去了，连已经下载好的也不见了？**\n\n**两件事，分开看。**\n\n**被踢出去**：手机息屏或切到别的 App 之后，系统会回收后台的网页，导出当场断。\n**v1.18 起脚本会在导出期间请求「保持屏幕常亮」**，能挡住屏幕自动熄灭；\n但**挡不住你手动锁屏或切走**，那两种情况下系统仍会收回。\n所以手机上导大批量时：**别锁屏、别切 App，把手机放着让它跑完。**\n\n**已经下载好的也不见了**：先别急着重导，**很可能还在**。\n不少安卓浏览器重启之后会清空**它自己那个下载列表**，但文件还在手机里。\n用系统自带的「文件」App 去 **`内部存储 \u002F Download`** 翻一下，八成都在那儿。\n\n真的没有的话，那是它们还没写完就被中断了——只能重导那几个。\n\n**Q：安卓上导完了，浏览器的「下载」列表里却是空的 \u002F 找不到文件？（X浏览器实测）**\n\n**浏览器的下载记录和手机里的文件是两回事。** 有用户在 X浏览器 上导完，\n面板里明明写着 `mufy_xxx_2026xxxx.zip 0.01 MB`，而浏览器的 **Downloads 是「No record」**——\n这类浏览器对网页内生成的文件**经常压根不记这一笔**，但文件是写下去了。\n\n按这个顺序找，一分钟内能定：\n\n1. **就在那个下载页上换个标签。** X浏览器的下载界面顶上有 `Directory` \u002F `Downloads` \u002F `Clean` 三个标签\n   —— 你看的是 `Downloads`（空的），**点左边那个 `Directory`**，那是文件夹视图，多半就在里面。\n2. **用手机自带的「文件管理」App**（最靠谱）：去 **`内部存储 \u002F Download`**，按时间倒序；\n   找不到就搜 **`mufy_`** 或 **`.zip`**。\n3. **还是没有，就点面板里那个「⬇ 手动保存」链接**——它就是为这种情况留的，\n   点一下会重新触发保存。⚠️ **别关面板**，关了链接就没了，只能重导一次。\n\n> 💡 **文件只有几 KB \u002F `0.01 MB` 是正常的**：只聊过一两轮的角色本来就这么小，不是没导全。\n> 想确认内容，解开看 `00_目录.md` 就行。\n\n> ⚠️ X浏览器这条路一直别扭的话，换 **Via 浏览器**（同样自带脚本功能）\n> 或 **火狐 + Tampermonkey**，它们的下载行为规矩一些。\n\n> 💡 **手机上导几百个角色，本来就是这个工具最吃力的场景**（每个角色一个文件＝几百次下载）。\n>\n> **v1.19 起断了不用从头来**：面板上有个「**从第几个角色开始**」。\n> 日志里每个角色都带序号（`✅ [37\u002F211] 【某某】…`），\n> 被打断之后看最后成功的是第几个，下次填它的下一个接着跑就行。\n> ⚠️ 顺序按「最近聊过」排，**中途别去聊天**，不然编号会变。\n>\n> 要省事还是**用电脑导全量、手机只负责读**。\n\n**Q：导出跑到一半，文件却一个都没出现？**\n八成是「下载前询问每个文件的保存位置」没关，或者「允许下载多个文件」没点允许。\n\n**Q：手机上（或电脑上）换字体没反应？**\n\n**字体不是跟着网页下载的，它用的是你设备里已经装了的字体。**\n本仓**不附带字体文件**（不代第三方字体做分发），所以「京華老宋 \u002F 站酷小薇 \u002F 朝華正文 \u002F 庆科黄油」\n这几款**只有你自己装过才会生效**——手机上一般都没有，切了自然没变化。\n\n现在列表里加了三个带「**（手机可用）**」的：**系统宋 \u002F 系统黑 \u002F 系统楷**，\n用的是 iOS、安卓自带的中文字体，**手机上切得动**。\n电脑上想用那几款好看的，把字体装进系统，网页里就会自动认出来。\n\n**Q：阅读器说「一个 zip 都没有」？**\n你多半选了云盘目录。先把文件夹复制到本地硬盘再选。\n\n**Q：有几个压缩包的文件名是一串字母数字，不是角色名？**\n\n**那说明这张角色卡已经被作者下架或删掉了**，不是脚本出错。\n\n卡片没了之后，连「这个角色叫什么」都取不到，脚本就退回用角色 ID 的前 8 位当文件名——\n**但聊天记录照常完整导出，正文一条不少**。这一条在真实账号上核实过：文件名变成字符串的\n那几个，去 mufy 上查确实都已经下架了。\n\n想认出是谁：打开包里的 `00_目录.md`，或者随便点开一篇 md 看看正文，一眼就知道了。\n（改文件名的话，把开头那串换成你认得的名字就行，不影响内容。）\n\n**Q：文件名写的是 A 角色，点进去却是 B 角色的聊天记录？**\n\n**这是一个真 bug，v1.20 已修。** 抱歉。\n\n原因：文件名要先「洗」一遍才能给操作系统用——`\u002F : * ? \" \u003C > |` 这些字符会被换成 `_`，\n连续空格压成一个，太长的还会截断。于是**两个不同的角色名，可能被洗成同一个文件名**\n（比如「夜色\u002F温柔」和「夜色:温柔」都变成 `夜色_温柔`）。\n\n旧版判断\"要不要在文件名里补角色 ID 来区分\"时，**比的是原始角色名**，\n就认为这两个不重复 → 两个压缩包同名 → 浏览器把后下载的那个存成 `xxx (1).zip`。\n**谁拿到\"正名\"取决于下载先后**，于是名字和内容就对不上了。\n\nv1.20 改成按**洗过之后的文件名**判重，并且在导出过程中再挡一道，\n绝不允许两个角色写出同一个文件名。\n\n**已经导出来的怎么办？** 不用重导也能认出来：\n每个压缩包里的 `00_目录.md` 开头写着真正的角色名，\n`_原始数据.json` 里还有 `characterId`。对着改一下文件名就行。\n（想省事就更新到 v1.20 重导那几个。）\n\n**Q：在 mufy 里往上翻聊天记录，一直弹 `Request failed with status code 429`？**\n\n**429 是 mufy 的服务器在说「你请求太频繁了」，不是脚本坏了，也不是你手机的问题。**\n它是**临时**的，不会弄坏你的记录，也不是封号。\n\n⚠️ **卸载篡改猴 \u002F 删脚本救不了这个**：往上翻时发请求的是 mufy 网页自己，\n跟你装没装脚本无关（尤其你在电脑上导出、却在手机上翻的时候，手机上本来就没跑脚本）。\n\n三个常见诱因，按顺序试：\n\n1. **刚跑完大批量导出** —— 短时间内特别容易撞上。**停手等 30–60 分钟**，\n   这段时间别反复去点，越点越容易把限流续上。\n2. **开着加速器 \u002F VPN \u002F 代理** —— 出口 IP 是共享的，很容易被当成异常流量。\n   关掉，或者换个网络（WiFi ↔ 流量）再试。\n3. **连续快速往上翻** —— 每翻一次就是一次请求，慢一点。\n\n**想分清是账号被限还是网络被限**：拿另一台设备 \u002F 另一条网络打开 mufy 翻同一个角色。\n一边正常一边不行 → 是那条网络的问题；两边都不行 → 账号层面的临时限流，等着就好。\n\n> 💡 **导出的意义就在这儿**：记录已经在你自己硬盘上了，用网页阅读器或电子书随时能读，\n> 不用再指望 mufy 那边翻不翻得动，也不会再触发任何限流。\n\n**Q：报错 HTTP 403 是什么意思？**\n\n403 不是「没登录」（那是 401），是**服务器认得你，但这次不让过**。两类常见原因：\n\n1. **站点前面的防护把请求当成了机器人。** 开着加速器 \u002F VPN \u002F 代理、网络环境异常、\n   或者短时间请求太密，都可能触发。**关掉加速器、换个网络、等几分钟再试**，多半就好了。\n2. **这个角色或资源，你的账号确实没有权限看。** 那就只能跳过它。\n\n**v1.19 起错误信息里会直接写出这两条**，不再只甩一个数字。\n日志里那一行还会带上是哪个接口、哪个角色，方便定位。\n\n**Q：提示「续不上登录态」？**\nmufy 的登录凭证只活 15 分钟。脚本会自动续，真提示这句就是掉登录了，\n刷新 mufy 页面（必要时重新登录）再来。\n\n**Q：跑到一半有个角色报错了？**\n不影响其他角色。**v1.13 起**单个角色失败会跳过继续跑，日志里当场标出来，\n结尾再汇总一次「成功几个、失败几个」并列出失败的角色名和 ID ——\n拿那个 ID 用「手动填角色 ID」补一遍就行。\n\n唯一的例外是**掉登录**：那不是「这一个角色的问题」，继续跑只会刷出几百条一样的错，\n所以会整批停下来，让你刷新 mufy 页面（必要时重新登录）再来。\n\n**Q：结尾说「有 N 段没导完整」，怎么知道是哪几段？**\n\n**v1.24 起会直接列出来**，不用一个个点开找：\n\n```\n🔴 有 2 段没导完整，分别是：\n   · 【某角色】2026-05-20 那段　接口说共 1458 条，只取到 1000 条（换小页重试过，还是这么多）\n   · 【另一个】2026-06-02 那段　…\n```\n\n对应文件的开头也仍然有同样的红字。\n\n**Q：某个存档导出来只有 1KB，点开只有几句话？**\n\n**这一段的完整内容脚本没拿到，但通常救得回来。**\n\n发生了什么：mufy 的存档记录本身只保存**一问一答**，正文要另外按 session 去取。\n有些**很久以前的存档**，那个取正文的接口会一条都不返回；脚本这时只能退回去写存档\n自带的那一对——所以文件会比当年真聊的那些短得多（常见的只剩 1KB 上下，具体多小\n取决于那一问一答本身有多长）。\n\n**救法（用户实测有效）：**\n\n1. 去 mufy 里找到那个存档，**把它「载入」**，让它变成你当前正在聊的那一段\n2. 回来**重新导出这个角色**\n\n载入之后接口就给得出全文了，导出来的就是完整记录。\n\n**v1.28 起这件事不再是静悄悄的**：这样的段在文件开头、`00_目录.md` 里\n（红点标记）、以及导出结束时的日志里都会写明白，还会告诉你上面这个救法。\n以前它跟一段真的只聊了两句的对话长得一模一样，根本分不出来。\n\n**Q：同一份聊天记录，怎么导出来了两份？**\n\n因为你在 mufy 里**载入过某个存档**。载入之后它同时又成了这个角色的\n「最后一次聊天」，于是存档那条路和「最后一次聊天」那条路各给出一个\nsession，内容却是同一份——两段的条数和文件大小会分毫不差。\n\n**v1.28 起会自动合并**：只有**一字不差**的两段才合并（载入之后你又接着聊过的，\n条数就不一样了，那是两段真不同的记录，不会碰）。合并时留下有存档的那一份\n（标题用你写的备注更好认），日志和 `00_目录.md` 里都会写一句「已合并 N 段重复的」，\n所以段数少了不是丢了东西。\n\n**Q：接口说共 1156 条，实际只取到 974 条——是 mufy 把记录弄丢了吗？**\n\n**是。已经有两位用户各自查清了这件事**：在 mufy 里把那段往上翻到顶，\n**那边确实就只剩这些**——mufy 迁移过服务器，并且发过公告说会丢一部分聊天记录。\n**它返回的总数还是丢失之前的数字**，所以才会出现「接口说 1156、实际只有 974」。\n\n也就是说，看到这个提示时，少掉的那些**在 mufy 上通常也已经翻不出来了**，\n不是脚本没抓到。**v1.26 起提示里会把这一点写清楚**，v1.28 又补了一句：\n这种情况**重导多少次都是这么多**，不用白等。\n\n想确认是哪一种，自己判一下：\n\n**去 mufy 里打开那一段，往上翻到底。**\n\n- **mufy 自己也只显示得出 900 多条** → 那边就只有这些，脚本没法凭空变出来\n  （可能是对方的服务端只让翻这么深，也可能真的少了）\n- **mufy 能翻出 1156 条、我们只导到 974** → 那是我们的问题，**请把角色名和这段的日期告诉我们**\n\n**v1.24 已经先尽了一份力**：发现拿到的比接口说的少时，会**自动换一种翻页方式重试一遍**，\n两次结果按 ID 合并去重。测下来这能救回一类情况（服务端对大页翻页有深度限制时，\n小页能接着往下翻）；如果换了还是一样多，日志里会写明「换小页重试过，还是这么多」——\n那就不是我们没尽力，是那边给不出来了。\n\n**Q：「全部合并成一份 Markdown」是什么意思？是把所有东西都装进去吗？**\n\n**不是。它决定的是\"产物长什么样\"，不是\"导多少\"。**\n导多少由**上面那一栏**（当前角色 \u002F 全部聊过的角色 \u002F …）说了算，这一栏只管形状：\n\n| 选哪个 | 出来是什么 |\n|---|---|\n| **每段对话一个文件（ZIP）** | 一段存档一个 `.md`，打包成一个压缩包，里面还有 `00_目录.md` 索引 |\n| **全部合并成一份 Markdown** | **这一个角色的所有段落**接成**一整个 `.md`**，从头翻到尾 |\n\n所以选「**全部聊过的角色**」＋「合并」＝ **每个角色各出一份 md**，\n**不是**所有角色挤进一个文件（点导出时的确认框也会写「每个角色一份 Markdown」）。\n\n**合并那一份里有什么**：角色名、统计（存档数 \u002F 对话数 \u002F 消息数 \u002F 导出时间）、\n**开场白单独一节**，然后一段一节按顺序排下来；该有的提醒\n（「这段只有存档摘要」「这段和另一段重复、已合并」）也都在。\n**比 ZIP 少的只有 `00_目录.md`** —— 合并版靠标题分节，用不着索引。\n\n⚠️ **不包含人设面具和你自己的角色卡。** 那是「导哪些」里另外的选项，要单独再导一次。\n\n⚠️ 勾了「附带 JSON 完整备份」的话，这条路会**另外单独下一个 `.json` 文件**\n（不像 ZIP 那样打包在一起），别以为漏了。\n\n**怎么选**：想**一口气通读**用合并；想**当备份、方便查某一段**用 ZIP。JSON 两种都建议勾着。\n\n**Q：勾了「清理 think \u002F 状态栏 HTML」，会把状态栏里的内容删掉吗？**\n\n**不会——状态栏里的字一个不少，被拆掉的是包着它的标签。**\n`\u003Cdiv>` `\u003Cspan>` `\u003Ctable>` `\u003Ctd>` 这类标签会被去掉，**标签之间的文字全部保留**：\n好感度、时间、地点、数值都还在。\n\n⚠️ **但排版会散**：`\u003Cbr>` 这种换行标签也在拆除名单里，所以原本分好几行的状态栏\n**可能会挤成一坨**。内容没少，就是不好看了。\n\n**真正会被整段删掉的只有三种**：\n\n| 会整段消失 | 说明 |\n|---|---|\n| `\u003Cthink>...\u003C\u002Fthink>` | 连里面的内容一起——这本来就是这个选项的主要目的 |\n| HTML 注释 | 给模型看的备注，读起来是纯噪音 |\n| `\u003Cstyle>` \u002F `\u003Cscript>` 块 | **所以状态栏靠 CSS 上的色、画的框会没，字还在** |\n\n⚠️ 一个例外：**状态栏整个被包在 `\u003Cthink>` 里面的话，会跟着一起没。**\n（另外 `\u003Cdetails>` \u002F `\u003Csummary>` **不在**拆除名单里，用它搭的状态栏会原样保留，见上面那条。）\n\n**最要紧的一句**：不管你勾不勾，**`_原始数据.json` 里永远是完整原文，一个字都不动。**\n内容不会丢，最坏也就是回 JSON 里翻。\n\n**怎么选**：想**读着干净**（当小说翻）就勾上；想**保住状态栏的原样排版**就别勾——\nmd 里会留着原始 HTML，用支持 HTML 的阅读器打开还是原来的样子。\n**EPUB 那条路一律清理**，不管你勾不勾：电子书格式不允许留 HTML 碎片。要原样就看 md 或 JSON。\n\n**Q：导出的长对话好像少了内容？（书从中间开始 \u002F 前面完整后面缺失）**\n\n**第一步：看导出结束时那段日志的最后几行，不用打开任何文件。**\n\n脚本每次收尾都会把有问题的段**单独用红字喊出来**。所以：\n\n- **没有 🔴 红字** → **接口说有多少条，脚本就拿到了多少条，一条没漏。**\n  绝大多数情况下这就等于\"完整\"，那\"少的那些\"是 mufy 那边已经没有了。\n  ⚠️ **但有一个例外，见下面那条**——所以如果你那段特别长，别只看这一条就下结论。\n- **有 🔴 红字** → 照下面这张表对号入座，三种情况救法完全不同：\n\n| 红字写的是 | 什么意思 | 怎么办 |\n|---|---|---|\n| 「第 N 页取失败」 | 抓取途中网络抖了 | **把那个角色单独重导一次**，通常就好 |\n| 「接口说共 N 条，只取到 M 条」 | 多半是 mufy 那边丢了（见上一条） | 重导也是这么多；去 mufy 里翻到底自己确认一下 |\n| 「只有存档摘要」（文件才 1KB） | 接口一条正文都没给 | **在 mufy 里把那个存档「载入」再重导**（见上面那条） |\n\n**第二步：去 mufy 里自己确认一眼。** 打开那个角色，**一直往上翻到最顶**——\n\n- **翻得到最早那几句** → 那是接口没给全，**请把角色名告诉我们**；\n- **翻不到、mufy 里也是从那儿开始的** → 那边确实只剩这些了，脚本变不出来。\n\n⚠️ **千万别为此去删存档。** 脚本正是靠存档列表才找得到那些老会话的\n（见上面「[你现有的备份可能是缺的](#️-最重要的一件事你现有的备份可能是缺的)」）——\n**删掉之后，你担心的\"前面的记录没了\"才会真的发生。**\n\n> 🔴 **例外：一整段上千条的对话，接口自报的总数本身就可能是被截过的 —— 而且这一种我们救不回来。**\n>\n> 一位用户拿 mufy 官方导出对过账（**那一次官方那边还留着早期内容**，另一位用户\n> 三天后再导时官方那份也只剩中段了，见下面 📌）：同一段对话官方那边 **2971 条**，\n> 而接口说的和我们拿到的**都是 1000** —— 两个数一样，所以旧版以为拿全了、**一声不吭**。\n>\n> **v1.35 起判据换了**：不再看接口自报的总数，**只看「这一页装满了没有」**——\n> 满页就继续要下一页，出现不满的一页才算到头。所以上面这种「总数撒谎」\n> 已经不会再让脚本提前收手了（v1.33 \u002F v1.34 那两轮补丁也被它吸收掉了）。\n>\n> 🔎 **同版加了长段体检**：一段超过 500 条时，导出日志和 `00_目录.md` 里会写明\n> **「接口说 N 条 \u002F 实际取到 M 条 \u002F 最早一条是哪天」**。\n> 看最早那个日期，你自己就能判断有没有缺前面 —— **不用再导一遍去试。**\n>\n> 💡 **怎么读这几行**：如果那一段是「**接口说多少＝实际取到多少**」，\n> 而**最早那条的日期比你印象里的晚**，那就是**接口在那之前不给了**，\n> 不是脚本没抓到 —— **别再重导了**，重导多少次都是这些。\n>\n> 🔑 **重点不是\"哪一年\"，是\"这一段有多长\"。**\n> 常有人问「为什么有人能完整导出 2025 年的记录，我却不行」——\n> 差别不在记录多老，在**你的历史是怎么切成段的**：\n>\n> | | 结果 |\n> |---|---|\n> | **段短、段多**（几十上百条一段，平时按过「保存并开启新对话」） | ✅ **不管多老都导得全**，因为往回翻的深度从来没深过 |\n> | **一整段就上千条**（一路聊下来没存过档） | ⚠️ 早的那部分**够不着**，书就会「开场白之后直接跳到中间」 |\n>\n> （实测过一个 25000 条的账号，992 段、**平均一段 25 条**，一条不缺；\n> 而撞上这个的两位用户，都是**一两段、每段上千条**。）\n>\n> 📌 **所以预防办法只有一个，而且真的有用**：\n> 在 mufy 里适时按「**保存并开启新对话**」，别让一段长到上千条。\n> 段一多一小，就永远碰不到这个坎。\n> 已经撞上的，更早的内容只能走 **mufy 官方的引继码导出**（那是另一条路）。\n>\n> ⚠️ 但**接口真的不给的那部分，谁也变不出来**：\n> **在那位用户的那一段上，我们试过的三种要法都停在 1000**\n> （`pageSize=500 × 2 页` \u002F `从第 3 页往后要` \u002F `一次请求要 2000 条`）；\n> 她在 mufy 网页里往上滑也翻不回去。**这一段更早的内容，这个脚本拿不到。**\n> （探测留着：真捞到了会在日志里写「📈 往后又翻出 N 条」，没这行就是没捞到。）\n>\n> 📌 **这一例后来的进展，一并交代**：她重导拿到 **2026 条**（两段：**1026 + 1000**），\n> 离官方那份的 **2971** 仍差约 **945 条**。\n> 而 **1026 那段，v1.34 及以前根本不会去探它** —— 老判据要求「正好拿满 **且是 500 的整数倍**」，\n> 1026 不是，于是它抓到 1026 就收手了，**第 4 页从来没被问过**。\n> **v1.35 换掉判据之后这个洞就没了**（不再依赖任何\"整数倍\"）。\n> 所以：**一整段上千条的对话，用 v1.35 再导一次是值得的**；\n> 导完看那行 🔎 长段体检里的「最早一条」，就知道有没有够到你记忆里的开头。\n> **那更早的内容怎么办？先试 mufy 官方自己的导出**（它出的是一个 `.txt`）——\n> **但别把它当救命稻草，两位用户的结果是相反的**：\n>\n> | | 官方导出的结果 |\n> |---|---|\n> | 用户 A（8\u002F7 导的） | ✅ 拿到了 **2971 条**，从最开头就有 |\n> | 用户 B（8\u002F10 导的） | ❌ **和这个脚本导的一样，也只有中段**，起点、时间都一模一样 |\n>\n> **所以真正的结论不是\"换条路导就能拿回来\"**：两条路都拿不到的时候，\n> 那部分在 mufy 那边就是没有了。**已经导下来的每一份都留着**，\n> 不同工具、不同时间导的产物合起来，通常比任何单独一份都全。\n>\n> 🕐 **⚠️ 别拿书里那个「⏰ 时间」判断缺没缺** —— 那是**剧情里的时间**\n> （角色扮演状态栏写的，可能是 `2024\u002F7\u002F27` 这种），**和真实时间没有关系**。\n> 要判断有没有缺前面，**看体检行里的「最早一条」**，那个才是真实日期。\n> （真有人拿剧情时间对过账，结论全错——包括我们自己。）\n>\n> 💡 **同时做这件事减少以后再丢**：在 mufy 里**按「保存并开启新对话」**，\n> 让一段别长到上千条。段一多一小，每段都离那个坎远远的。\n> ⚠️ 只有\"一整段就上千条\"才会碰到这个。两万条分散在几百段里的那种完全不受影响。\n\n> 📌 **想自己较真的话**（可选，不看也不影响）：勾了「附带 JSON 完整备份」的话，\n> `_原始数据.json` 里每段都有 `expectedCount`（接口说共多少条）和\n> `messageCount`（实际拿到多少），两个数一样就是完整的。\n> 结尾日志判断的就是这两个数，所以**日志没红字＝这两个数处处相等**，不用自己翻。\n\n> v1.8 之前有个坑：长对话翻页翻到一半失败时，**已经抓到的几百条会被整个丢掉**，\n> 退回成存档里的一问一答（2 条），而且只在角落留一个小小的 ⚠️。\n> 现在改成抓到多少留多少、并在文件开头和结尾都明确报出来。\n> **长对话才需要翻页，所以这个坑专挑长记录下手** —— 如果你之前用旧版导过，值得重导一次。\n\n---\n\n## 附：手机上全程走完（iPhone \u002F 安卓，两边都有人走通）\n\n只有手机、没有电脑也能用。**v1.10 起电子书直接在浏览器里生成，不再需要 Python，\n所以整条链路手机上就能闭环**：装脚本 → 导出 → 出 EPUB → 读。\n\n> ✅ **iPhone（Safari + Userscripts）已实测走通全程。**\n> ✅ **安卓也走通了**：有安卓用户照着下面这份教程从头走了一遍，没有遇到别的问题。\n> （我们自己没有安卓设备，这一节的验证来自真机用户，不是我们测的。）\n\n### iPhone \u002F iPad\n\n**1. 装 Userscripts**（App Store 搜，免费开源）。iOS 上没有 Tampermonkey，那个只有 Mac 版。\n\n打开它一次，它会让你**指定一个存脚本的文件夹**——在「文件」App 里新建一个就行。\n\n**2. 打开扩展**：设置 → Safari → 扩展 → **Userscripts** 打开，网站权限给「允许」\n（选「始终允许」省事，不然每次都要点一下）。\n\n> 🚨 **别在「无痕浏览」里用。** 已有用户卡在这儿：脚本装好了、Userscripts 面板里\n> 也看得见而且是启用状态，**就是不出按钮**——原因是他开着无痕。\n> 换成普通标签页（必要时把 Safari 完全关掉重开）就好了。\n\n**iPhone 上怎么确认脚本本身是好的**：在 mufy 页面点地址栏的 **ᴀA → Userscripts**，\n弹出的面板里——\n\n- **右上角那个总开关**要是**开着**的（控制要不要往页面里注入脚本）\n- 列表里能看到「**Mufy 批量导出聊天记录**」，而且是**亮白色**的\n  （**灰色 = 这条被停用了**）\n\n这两样都对、却还是没按钮的话，问题就不在脚本上，看上面那条「无痕」和网站权限。\n\n**3. 把脚本放进去**：Safari 打开下面这个地址，全选复制——\n\n\u003Chttps:\u002F\u002Fraw.githubusercontent.com\u002Fwillwefind\u002Fmufy-batch-export\u002Fmain\u002Fmufy-batch-export.user.js>\n\n然后点地址栏左边的 **ᴀA \u002F 拼图图标 → Userscripts → 新建脚本**，粘贴进去保存。\n\n> 💡 **更省事的一种**：直接在 Safari 里打开上面那个网址，页面上多半会自己冒出一条\n> 「**Userscript Installed \u002F Tap to install**」的横幅，**点它就装好了**，不用复制粘贴。\n> **以后更新也走这条**：再打开一次这个网址 → 横幅变成\n> 「**Tap to re-install**」→ 点一下就覆盖成新版。\n> （🚨 点之前先**下拉刷新**一下页面 —— 那个网址有几分钟缓存，不刷新可能装到的还是旧版。\n> 装完记得回 mufy 页面刷新一次，理由见下面那条。\n> 想确认版本：打开导出面板，标题右边写着 `v1.37` 就是新的。）\n\n> 🚨 **保存完，回到 mufy 那个标签页刷新一次。** 脚本只在**页面加载的那一刻**注入，\n> 你装脚本时开着的那个标签页是\"装之前\"的，不刷新就永远不出按钮\n> ——面板这时候显示的是 `No matched userscripts`，看着像没装上，其实只差一次刷新。\n> **已有 iPhone 用户卡在这一步。**\n\n**4. 导出**：Safari 打开 mufy 登录 → 随便进一个角色的聊天页 → 左下角出现\n**「⬇ 批量导出」** → 范围选「当前角色」、输出方式选「**每个角色一本电子书（EPUB）**」→ 开始。\n\n**5. 读**：Safari 右上角的下载箭头（或「文件」App → 下载）里就是那本 `.epub`，\n点开 →「用其他应用打开」→ 微信读书 \u002F 图书 \u002F 静读天下。\n\n### 安卓\n\n安卓上的 **Chrome 装不了扩展**，所以不能照电脑那套走。有两条路，任选其一。\n\n#### 路线 A：X浏览器 \u002F Via 浏览器（推荐，不用装插件）\n\n这类国产轻量浏览器**自带脚本功能**，装个浏览器就够了，不需要 Tampermonkey。\n\n> ⚠️ **先说一个特别容易走错的地方：**\n> 这些浏览器里有个「**精选用户脚本**」页面（写着\"这里汇总了一批常用的油猴脚本\"）。\n> **那是浏览器自带的脚本市场，我们这个不在里面**——在那儿翻遍了也找不到。\n> 要走的是下面「装外部脚本」这条路。\n\n**1. 装浏览器**：应用商店搜 **X浏览器** 或 **Via 浏览器**（都是几 MB 的小软件）。\n\n**2. 装脚本 —— 先试最省事的：**\n\n用它打开下面这个地址：\n\n\u003Chttps:\u002F\u002Fraw.githubusercontent.com\u002Fwillwefind\u002Fmufy-batch-export\u002Fmain\u002Fmufy-batch-export.user.js>\n\n浏览器认得 `.user.js` 这种文件，通常会直接弹出「**是否安装此脚本**」，点安装就完事了。\n\n**3. 没弹出来的话，手动加：**\n\n- 打开浏览器**菜单**（右上角三个点，或底部的 ☰）\n- 找**脚本**相关的入口——不同版本叫法不一样，可能是「**脚本管理**」「**用户脚本**」\n  「**油猴脚本**」，位置可能在「工具箱」或「设置」里\n- 进去之后点「**新建**」或「**添加**」→ 把上面那个网址填进去；\n  如果只能粘代码，就回到那个网址**全选复制**，整段粘进去保存\n\n**4. 回 mufy**：浏览器打开 mufy 登录 → 进任意角色的聊天页 → **刷新一次** →\n左下角出现「⬇ 批量导出」。\n\n#### 路线 B：火狐（Firefox）安卓版 + Tampermonkey\n\n想用和电脑上一样的 Tampermonkey 就走这条。火狐安卓版支持扩展（**只能装它推荐列表里的**，\nTampermonkey 在列表里）。\n\n1. 应用商店装 **Firefox**\n2. 菜单（右下角三个点）→ **扩展 \u002F 附加组件** → 搜 **Tampermonkey** → 添加\n3. 然后点第 2 步那个脚本地址，Tampermonkey 会弹安装页，点**安装**\n4. 打开 mufy 登录 → 进聊天页 → 刷新 → 左下角出现按钮\n\n> 🚫 **别用 Kiwi 浏览器了**。它以前是安卓上装 Chrome 扩展最常见的选择，\n> 但作者已经停止开发，不建议再依赖它。\n\n#### 导出与读\n\n- **导出**：点「⬇ 批量导出」→ 范围选「**当前角色**」（先只导一个试）→\n  输出方式选「**每个角色一本电子书（EPUB）**」→ 开始导出。\n- **文件在哪**：一般在 `内部存储\u002FDownload`，用系统自带的「文件」App 找。\n  浏览器自己的「下载」列表里也能直接点开。\n- **读**：点那本 `.epub` →「用其他应用打开」→ **静读天下 \u002F 微信读书 \u002F 多看 \u002F Moon+ Reader**。\n\n#### 安卓特有的两个坎\n\n- **第一次批量下载会被拦一下**：浏览器可能弹「是否允许下载多个文件」，点允许。\n  有的浏览器还会每个文件都问一次保存位置——在浏览器设置里把「下载前询问保存位置」关掉。\n- **别切后台、别锁屏**（这条比 iPhone 上更要紧，安卓杀后台更狠）。\n\n### 手机上的几条注意\n\n- **先只导一个角色试**，确认整条路通了再说。\n- **手机上建议选 EPUB，别选 ZIP**：几百个 zip 灌进手机下载目录很难管，而且在手机上也没法用\n  网页阅读器读起来也挤（手机上用「直接选 zip 文件」多选整包，能用但界面是按大屏排的）。\n- ⚠️ **一次导几百个角色，手机上没实测过**（实测的是单个角色）。要整体备份，\n  能用电脑就用电脑；只有手机的话建议分批导，别一次点全部。\n- ⚠️ **跑的时候别切到别的 App、别锁屏**。手机浏览器会把后台页面暂停甚至直接回收，\n  导出会断。**v1.18 起脚本会请求「保持屏幕常亮」**，但那只挡得住屏幕自动熄灭，\n  挡不住你手动锁屏或切走——把手机放着让它跑完最稳。\n\n---\n\n\u003Cdetails>\n\u003Csummary>更多设置与技术细节（点开）\u003C\u002Fsummary>\n\n### 面板选项\n\n> 这张表其实是**三组**，每组各选一个，互不替代：\n> **① 导哪些**（当前角色 \u002F 全部聊过 \u002F 关注 \u002F 手动填 \u002F 面具 \u002F 角色卡）→\n> **② 产物长什么样**（ZIP \u002F 合并成一份 md \u002F EPUB \u002F 酒馆 jsonl）→ **③ 两个开关**。\n> ②**不影响导多少**，只决定东西打包成什么形状 —— 这一点最容易看混，\n> 详见「[全部合并成一份 Markdown 是什么意思](#常见问题)」那条 FAQ。\n\n| 选项 | 说明 |\n|---|---|\n| **当前角色（本页）** | 只导你正在看的这个角色 |\n| **全部聊过的角色** | 想整体备份就选这个 |\n| **全部已关注角色** | 你点过关注的全部角色，**包含从没聊过的**（会自动跳过并报数） |\n| **手动填角色 ID** | 从地址栏 `roleId=` 后面那串复制过来 |\n| **每包最多多少段对话** | 留空＝一个角色一个包。对话上百段的角色填 **20**，改成一批批地抓、抓完就放，**内存峰值只跟一批有关**（**v1.23**） |\n| **从第几个角色开始** | 只在成批导时出现。**中断后接着跑用**：看日志里最后成功的是第几个，下次填它的下一个（**v1.19**） |\n| **人设面具（全部）** | 导的是面具库，不是聊天记录。见[这一节](#顺带把人设面具也导出来) |\n| **我创建的角色卡（全部）** | 导的是你自己写的卡，含图片。见[这一节](#你自己写的角色卡)（**v1.12**） |\n| **每段对话一个文件（ZIP）** | 默认。N 段对话 = N 个 md，打包成一个 zip |\n| **全部合并成一份 Markdown** | 想一口气通读时用。**一个角色一份**（不是所有角色挤进一个文件），开场白和每段对话在同一个 md 里依次排开 |\n| **每个角色一本电子书（EPUB）** | 直接出成品书，不用装 Python。一段对话一章，开场白单独一章，自带封面 |\n| **酒馆对话（.jsonl）** | 导进 SillyTavern 用。一段存档一个文件，含导入说明（**v1.21**） |\n| **清理 think \u002F 状态栏 HTML** | 只影响 Markdown 可读性；JSON 永远是完整原文。**EPUB 一律清理**（书是拿来读的）。⚠️ 状态栏的**字全保留、排版会散**，详见[这条 FAQ](#常见问题) |\n| **附带 JSON 完整备份** | 建议勾着，这才是真正的备份 |\n\n### 「关注」和「聊过」不是同一批人\n\n`isFollowed=true` 返回的是**你关注的全部角色**，包括从没聊过的，而不是两者的交集；\n反过来也有你聊过却没点关注的。想整体备份，选「全部聊过的角色」。\n\n实测某账号：关注 291 个，其中真的聊过 192 个，从没聊过 99 个，另有 20 个聊过但没关注。\n\n### 它是怎么工作的\n\n用到这几个接口，都带 `Authorization: Bearer \u003ClocalStorage['mufy-token']>`：\n\n| 接口 | 作用 |\n|---|---|\n| `GET \u002Fapi\u002Fcharacters\u002Fquery_session` | 角色列表（含 `lastSessionId`） |\n| `GET \u002Fapi\u002Fsessions\u002Fquery_archives?characterId=` | 某角色的存档列表 |\n| `GET \u002Fapi\u002Fdialogs\u002Fquery?sessionId=&characterId=` | 某段对话的全部消息 |\n| `GET \u002Fapi\u002Fcharacters\u002Fget?id=` | 角色名和 **开场白（`greeting`）** |\n| `POST \u002Fapi\u002Fmasks\u002Fquery` | 人设面具库（v1.11 用）。**是 POST**，字段叫 `page`（不是 `pageNum`），`pageSize` 上限 100 |\n| `GET \u002Fapi\u002Fcharacters\u002Flist?creatorId=` | 你自己创建的角色卡清单（v1.12 用） |\n| `POST \u002Fapi\u002Fcharacters\u002Fmetadata` | **作者视角**的完整卡片（body `{id}`）。`characters\u002Fget` 是读者视角，人设／情节设定／输出设定／正则一概没有 |\n\n流程：取角色列表 → 每个角色取存档 → 按 `sourceSessionId` 去重、再补上 `lastSessionId`\n→ 逐段抓全文 → 加上开场白 → 渲染 Markdown → 打包 ZIP → 浏览器下载。\n\nZIP 是脚本按格式自己拼的，压缩用浏览器原生的 `CompressionStream`，**不引任何外部库**。\n\nEPUB 说到底就是一个结构固定的 ZIP，所以 v1.10 把整套生成逻辑搬进了浏览器——\n封面用 canvas 画（不带任何字体文件，用系统自带的宋体），从此不需要 Python。\n`make-epub.py` 仍然保留，给「已经导过一堆 zip、不想重导」的人用。\n\n**两条路出的书是等价的**，这不是估计：在一个 200 多角色的真实账号上，\n两边各出了 211 本，逐项比对书 ID、章节清单、目录标题、以及每一章的正文全文，\n**211 本全部逐字节一致**。合规性用官方 epubcheck 5.1.0 校验：**0 errors \u002F 0 warnings**。\n\n> 移植时逮到过一个真差异：JS 的 `slice` 按 UTF-16 码元算，Python 的 `[:n]` 按字符算，\n> 标题里只要出现 emoji 或花体字（一个字占两个码元），两边就会截出不同长度。\n> 211 个里咬中 3 个。改成按码点截之后归零。\n\n请求之间留了 120–300ms 间隔，遇到限流会退避重试——**别改激进，那是别人的服务器。**\n\n### 超长记录：实测数字\n\n有人担心长对话会被吞。这里是**合成一段 1 万轮（2 万条消息）的对话**推过整条链路的实测结果：\n\n| 环节 | 结果 |\n|---|---|\n| 翻页抓取 | 40 次请求，2 万条**全到，0 重复 0 遗漏** |\n| 渲染 Markdown | 98 ms，单篇 24.5 MB |\n| 打包 ZIP | 448 ms，堆内存 33 → 50 MB |\n| 转 EPUB | 成书，单章 XHTML 21 MB |\n| **EPUB 在微信读书** | 真机导入，**打开正常、跳目录正常** |\n| **网页阅读器** | 2 万条一次性进 DOM（约六万个元素），**不卡** |\n\n结论：**不需要按章切分，也不需要分页渲染。** 一万轮以内不用做任何特殊处理。\n\n另外实测：`\u002Fapi\u002Fdialogs\u002Fquery` 的 `pageSize` 不限于 100（试到 2000 都接受），\n而且 100 \u002F 200 \u002F 500 三种页大小翻出来的唯一 `dialogsId` 集合**完全一致、0 重复 0 漏掉**——\n偏移量是准的。所以 v1.9 起默认每页 500，一万轮对话的请求数从 200 降到 40，\n**暴露在网络抖动下的机会少 5 倍**。\n\n真实性说明：合成文本是同一句重复，所以压缩率高得不真实（21 MB 的章压成 96 KB）。\n但压力点是**解压后**那 21 MB 的解析与渲染，那部分是真的。\n\n### 关于安全\n\n脚本读你浏览器里的 mufy 登录凭证，这是它能工作的前提。\n它**只把这个凭证发给 mufy 自己的接口**，不外传、不上报、不统计、不引第三方库。\n\n但你不该因为我这么说就信。源码在这儿摊着，三万字节，能读的自己读一遍，\n读不动的可以整段丢给任何一个 AI 让它讲给你听。\n**「作者说它安全」从来不是安全的理由，「你能自己查」才是。**\n\n往浏览器控制台粘代码本身有风险，浏览器弹的那句「不要粘贴不明代码」是对的。\n装 Tampermonkey 至少代码留在本地、随时可查。\n\n\u003C\u002Fdetails>\n\n---\n\n## License\n\nMIT。随便改随便传。\n","这是一个为 Mufy 平台设计的用户脚本工具，用于批量导出用户所有角色的聊天记录、人设面具及自定义角色卡，输出为结构化 Markdown 和 JSON 文件，并支持一键生成 EPUB 电子书。核心特点是完全基于网页端接口调用，无需后端服务；全链路适配移动端（iPhone Safari + Userscripts \u002F 安卓 X浏览器等），支持纯手机操作闭环；导出内容覆盖官方已下线或不可见的角色数据，弥补平台备份缺陷。适用于希望长期归档、离线阅读或迁移至 SillyTavern 等本地推理前端的 Mufy 用户。",2,"2026-08-10 02:30:10","CREATED_QUERY"]