扩展 v1.5.1 已发布
把你的豆瓣,备份到自己手里
这不单是一个孤立的备份工具,而是一套完整的数据链路方案:把豆瓣抓下来、存成十几年后依然打得开的标准档案、 解析出结构化数据、生成属于你自己的静态豆瓣,并能导出到你想去的地方。 整条链路的每个环节都完全独立,可以单独审查、随意替换,也可以按需只用其中一段。
从备份豆瓣到生成一个能浏览的完整站点,整条链路已经彻底打通,并且全部收敛在扩展内部完成。 扩展在你本地的浏览器中按你自己的节奏抓取,页面原样存为标准 WARC 格式; 点击「导出」,即可当场生成结构化数据、NeoDB 导入包,或是生成一个支持搜索、 具备固定链接、完全离线可看的个人存档站点—— 全程无需安装任何第三方软件。登录凭据与个人数据绝不离开你的设备。 实际效果不用凭空想象——sample.doubak.com 就是这么生成的。
需要 Chrome、Edge,或 Firefox 140 以上。两个 Chromium 商店提交的是同一份包
——同一条 CI 打出来的,所以装哪边都一样;Edge 也仍然能从 Chrome 应用商店装。
Firefox 那份是另一个包(-firefox.zip,两边的
manifest 不一样),同一条 CI 一起打出来的。
不想走商店的话,release
里那份 .zip 还是同一个包——注意它是商店的提交格式,
浏览器不能直接装 zip,要先解压再用开发者模式的「加载已解压的扩展程序」。
说明在这里。
零依赖、零构建步骤——仓库里的源码就是浏览器里跑的东西。
为什么要有它
豆瓣官方从未提供数据导出功能。十几年积攒的书影音标记、评分、短评、广播和日记,全系于一个随时可能被登出的账号; 尤其是那些注册手机号早已停用的海外用户,哪怕一次例行的短信验证,都可能意味着账号的永久失去。 现有的备份工具大多只是导出一份 CSV 表格或抓取一段纯文本——一旦豆瓣改版、条目被删、图片失效, 光凭手头那点零散文本,根本无法还原当时页面上真正看到的内容。
一个真实案例 短评绕开了敏感词,依然无济于事
样张站里记录了 8 个豆瓣已删除的作品(7 个游戏、1 部电影)。 其中这一页是 《返校》——赤烛 2017 年推出的那款台湾恐怖解谜游戏,今天在 NeoDB 上依然查得到, 只是在豆瓣上早已无法打开。不过本地档案里依然完整保留了当年的短评、四个标签「恐怖 台湾 解谜 历史」、 2017 年 1 月发布的两条广播,以及广播中固定下来的 ★★★★☆ 评分 (标记本身未打分,这颗星只保存在广播中)—— 「实在是一个政治题材的作品……可惜对政治题材十分不感冒」。
当年写下那段短评时,是刻意绕开敏感词写的:通篇只提「政治题材」, 具体涉及什么历史事件未着一字。但条目最终依然彻底消失。 豆瓣为何删除它,页面上从未说明;能确定的事实只有一条—— 真正消失的不仅是你写下的某句话,而是承载它的整个条目。 自我审查最多只能约束自己写下的字句,但平台删掉的却是它那一侧的所有记录。
因此,唯一未能留存的信息是作品原本的名字:如今页面上只显示「未知作品」, 档案里对应字段也是空的。广播的正文在发布那一刻便已固定, 但附在广播下方的作品卡片却并非如此—— 那是豆瓣在你每次访问页面时实时渲染的,因此在 2026 年去抓取 2017 年发布的广播, 附带的卡片也早已变成了「未知作品」。 上面提到的游戏名称来自作者本人的记忆,并非从抓取的档案中提取。
作品名称只有趁着条目尚未被删时抓取过才能留下来。这就是「及早备份一次」与「改天再说」之间最实在的差别。
这个项目其实从 2020 年就已启动。 上一版是用 Go 编写的命令行工具, 传统纯手工编码,目前已经归档;现在的版本则是通过 vibe coding 协作完成的,五天内完成了 112 次提交。 正因如此,项目更需要做到代码完全公开好懂:零外部依赖、无构建流程、仓库里的源码就是浏览器中运行的代码—— 你无需盲目信任作者或 AI 模型,直接查阅源码就能一目了然。 重新架构的理由收录在这篇日志中, 具体的开发历程则记录在这篇日志里。
和豆伴、豆坟有什么不一样
先澄清一个常被混淆的概念:「豆坟」和「豆伴」并不是同一个东西。 豆伴是真正的浏览器扩展; 而豆坟是他们为了方便无法访问 Chrome 商店的 Windows 用户,所打包的一个定制 Chromium 浏览器, 内置的依然是豆伴扩展。 因此很多时候「豆坟无法使用」只是那个特定浏览器的问题,并非备份方案失效—— 豆伴扩展本身完全可以直接安装在你日常使用的 Chrome 或 Edge 中。
豆伴的诞生比本项目早得多,许多人十余年的豆瓣记录都是借助它保存下来的。 两者最本质的定位差异在于:最终保存的是「从页面提取出的零散字段」,还是「原始网页本身」。
| 豆伴 | 豆备 | |
|---|---|---|
| 存下来的是 | 解析后的条目,存进扩展自己的库 | 页面原样,标准 WARC 档案 |
| 图片 | 不含(其 README 明确注明「备份下载的内容不包括图片」,需联网才能查看) | 完整抓取(用户自己上传的照片、条目封面图) |
| 断网之后 | 图片无法显示 | 离线完整可读,具备固定链接 |
| 导出 | Excel 表格 | 结构化数据、NeoDB 导入包、可搜索的静态站点 |
| 浏览器 | 只支持 Chromium 内核 | Chromium 内核,以及 Firefox |
表格最后一行在 2026-09 之前是「同样只支持 Chromium 内核」。虽然 Firefox 确实缺乏 File System Access 与 offscreen 接口,但真正受阻的仅仅是把文件直接写入本地磁盘这一步——扩展内部的 OPFS 本地存储模块一行代码都无需变动。因此在 Firefox 上导出的是一个 zip 压缩包, 解压之后与 Chrome 导出的目录逐字节完全相同,并非不同的数据格式。 Safari 目前依然无法支持。
什么时候选豆伴更合适? 如果你只想要一份随时查阅的简明清单,或者导入 Excel 进行日常统计,豆伴更加轻快直接, 也无需去了解什么是 WARC 归档。而豆备所多做的工作——原始快照、内嵌图片、完整离线浏览、永久固定链接——则是为了另一个深层诉求: 在未来某天条目彻底消失时,你依然能够确切知道当时页面上记录的全部细节。 前文提到的《返校》案例便是因此得以完整保留。
数据的一生
抓取是整个链路中唯一不可逆的关键一步,其余环节皆可重复运行。因此整套架构被拆分成独立的阶段: 先把原始页面完好存下,后续如何解析和提取可以从长计议——重新运行解析器毫无成本,但指望以后把已失效的页面重新爬取一遍却绝无可能。 从页面抓取到生成真正能浏览的网页,这条通路如今已全线贯通, 成品示范即为 sample.doubak.com。 对外导出的通道也已就绪——NeoDB、Letterboxd、Goodreads 所需的格式各不相同, 但它们都能直接基于你手头保存的同一份基础档案转换生成,无论何时导出都无需重新抓取。
-
01
抓取 已可用
通过浏览器扩展在本地运行。作为唯一不可逆的前提步骤,优先保障抓取质量。
-
02
档案 已可用
WARC + 结构化索引,格式独立制定规范。下游数据均可由其重新生成,而它无法逆向反推。
-
03
解析 已可用
原始档案 → 条目、评分、短评、时间。纯离线函数,逻辑调整后重新跑一遍即可。十份真实档案数秒内即可处理完毕。
-
04
结构化数据 已可用
输出八个标准的 NDJSON 文件,可用
jq直接检索。每次观测保留版本修订,用户创作内容与豆瓣条目资料解耦存储。 -
05
出口 已可用
直接生成个人静态站点,或是导出为 NeoDB、Letterboxd、Goodreads 的导入文件。数据自由迁移,不依赖任何第三方平台。
具体能做什么
抓取这一段 —— 现在就能用
-
本地抓取 已可用
在你自己的浏览器、用你自己的 IP 和节奏抓,没有服务器参与,也没有账号体系。 登录凭据和会话 cookie 不离开设备。遇到验证码它会停下来等你,而不是重试。
-
增量抓取 已可用
第二次只抓上次之后新增的部分,沿着上一份档案记下的下界回溯。 多份档案连成一条链,完整性是整条链的属性,不是单份的。
-
版本化抓取 已可用
同一个页面在链上被抓到过几次就留几份,捕获列表里分得清「本次新增」和「又抓了一次」, 并能翻出跨档案的版本历史。至于把两次的差别说清是「又看了一遍」还是「改了短评」, 那是解析器逐字段比对的活,现在也能用了(见下一组)。
-
连作品详情页一起抓 已可用
不只抓你的标记列表,每一部标记过的电影、书、音乐、游戏、舞台剧的详情页也抓下来, 连封面一起。这是「一份能留一辈子的静态豆瓣」的前提—— 标题、年份、评分、简介、封面都在档案里, 以后生成个人站点时不需要回头再找豆瓣要一次,而那时候还找不找得到,谁也说不准。 代价是它占了一份档案九成的体积,所以单独成段存放,不想要的话一条命令就能删掉。
-
原样存成 WARC 已可用
网页存档的国际标准,互联网档案馆用的就是它。原始字节、原始响应头,不做任何清洗。 用 ReplayWeb.page 或 pywb 可以直接打开重放, 不需要豆备本身。
-
连续性证明与覆盖率 已可用
每条路线都有清晰明确的起止范围与缺口记录,绝不含糊地只报一句「已完成」。 页面上豆瓣官方标称的数量同样如实记录,两相对比不一致本身就是重要的证据。
-
导出到本地文件夹 已可用
导出整条备份链时,每份档案独立存放在子目录中,导出完成后自动回读校验。 档案采用通用文件格式,保存在本地硬盘、同步到网盘或刻录光盘皆可。
解析与生成这一段 —— 也能用了
-
解析成结构化数据 已可用
档案 → 八个 NDJSON(标记 / 作品 / 广播 / 长文 / 豆列 / 相册 / 小组话题 / 加入的小组),纯函数、不联网,
jq直接查。 每次观察留一份修订,逐字段比对,所以「改了评分」和「改了短评」不会混成同一件事。 只需指定存放所有档案的目录即可,无需手动挑选链条—— 实测表明多次归档合并后正是完整的并集,单选任何一条都会遗漏数据。 -
生成你自己的豆瓣网站 已可用
一条命令从档案生成一个可搜索、有固定链接的个人存档站点, 成品就是 sample.doubak.com。 重建全程离线、零网络请求,双击
index.html就能看,不用起服务器。 真正的产物是 Markdown + YAML front matter,Hugo / Astro / Eleventy / Jekyll 都能接, 自带的那个骨架只有五个文件,删掉换主题就行。 -
发布成一个网站 已可用
npm run deploy可将静态站点文件推入仓库,通过 GitHub Pages 即可直接发布上线。 在发布前系统会提供一次完整预览,明确列出哪些内容将被公开—— 第三方内容默认排除,旧文件也会自动清理干净,绝不残留「链接仍在该页却已失效」的死链或幽灵页面。 -
导出到 NeoDB / Letterboxd / Goodreads 已可用
一条命令产出三家的导入文件,不联网——上不上传、什么时候传,都不影响你的档案。 NeoDB 收得最全:实测 2950 条标记里 2943 条能带走,连短评、标签、评分和书评一起; 剩下 7 条是豆瓣已经删掉、档案里连链接都没留下的作品, 那 7 条会被单独列出明确告知,而不会含糊地混在导入失败的报错里。 Letterboxd 只收电影、Goodreads 只收书,能带走多少、带不走什么,同样一条条数给你看。 反向转换则绝无可能:本地原始档案始终是无损的超集,这三个导出工具本质上都是面向外部平台的有损转换器。 NeoDB 这一路已经真的导进去验过,导完长这样: neodb.social/users/doubak ——跟 样张站是同一份档案的两种去处。
NeoDB 那一档现在默认出它自己的 NDJSON 归档格式 (旧的 CSV 还在,要显式要):多带走豆列、 不挂作品的日记、每条记录各自的可见性, 以及一条从广播还原出来的状态时间线—— 想看 → 在看 → 看过,每一步带着当天的日期和当天打的星, 豆瓣自己只留最后一次。 NDJSON 这一路也真导过了(2026-08-25,整份档案 17305 条记录,0 条失败), 导完长这样:neodb.social/users/immewx ——想看 1098 · 在看 71 · 看过 1774,电影 1473 · 剧集 638 · 游戏 598 · 图书 145 · 音乐 84 · 舞台剧 5,连同 712 个标签、6 份豆列和 2519 条状态历史。 导完之后还从 NeoDB 自己的导出功能把数据取回来逐字段对过一遍: 2979 个条目全部对上,每一类记录一条不差。
还没做的 —— 路线图上的
-
Letterboxd / Goodreads 真导一次 计划中
NeoDB 那两条路(CSV 和 NDJSON)都真导进去验过了, 这两家还没有。核心教训只有一条:「自以为理解了对方的代码逻辑」与 「对方系统真正成功入库」完全是两回事——此前在 NeoDB 的两次实际上传中,各自暴露出本地测试中无法预见的兼容问题。 在真正实测通过之前,对这两家目前只能谨慎表述为「符合已知规范」。
-
从别处导入 计划中
IMDb、Letterboxd、Goodreads、Trakt 本身都提供了官方导出功能,因此针对它们只需开发本地文件导入逻辑, 无需额外编写爬虫。本项目的浏览器扩展,正是专门针对「豆瓣官方不提供导出」这一痛点给出的工程解法。
-
外部链接补全 可选
补上 TMDB / Wikidata 交叉链接和多语言标题。跑一次、永久缓存, 下游任何环节都绝不允许强依赖该功能——如果静态站点在重建时还需要联网抓取外部数据, 就等于把本项目好不容易消除的外部依赖又重新带了回来。
样张展示
生成出来的网站实际效果如何,无需凭空想象—— sample.doubak.com 便是使用作者本人的真实豆瓣数据跑通整条流水线生成的,包含了十余年的标记、广播与短评。
- 2,940条标记
- 3,394条广播
- 3,045张图片,全部本地
- 0个外部请求
最后一项指标「0 个外部请求」是核心所在:页面中没有任何一个 src 属性指向外部站点。
作品封面与用户自传图片全部从离线档案中完整提取出来——
一份必须依赖联网、且必须在豆瓣服务器尚存时才能打开的备份,谈不上是真正的备份。
把整个仓库克隆到本地后,双击 index.html 即可在断网状态下完整浏览,无需启动任何本地服务。
示例站点采用的是生成器内置的最小骨架结构(仅五个模版文件)。生成器真正的输出物是
通用的 Markdown 与 YAML front matter,
因此若想套用任何现成的 Hugo 主题,只需移除 layouts/ 目录即可;
同样也可以自由接入 Astro、Eleventy 或 Jekyll 等各种现代静态站生成器——现有的成熟主题生态都可以直接作为它的模版库。
样张严格排除了任何第三方产生的内容:抓取环节便不会收集他人的回复、关注列表与豆邮;
转发进来的他人广播会依据 data-uid 自动过滤,他人上传的图片也绝不采集。
本项目早期的大量架构设计判断,均由前代命令行工具曾抓取的一份
782 MB 真实档案反复验证得出(覆盖 2022–2024 年共 20 个批次),其中便包括
「豆瓣官方统计展示的数量不能作为抓全与否的可靠证据」这一核心结论。
不让你的账号出事
账号被封是不可挽回的底线问题,绝不能心存侥幸。防封必须依靠扎实的架构设计,而不是寄希望于「使用时小心一点」。
- 信任边界严格限定在你的本地设备。我们曾深入评估过服务端抓取方案并予以否决——集中抓取不仅会让服务器本身成为隐私隐患,还会让所有用户受制于同一个全局抓取配额。
- 校验真实页面内容,而不只看 HTTP 状态码。豆瓣在触发封禁时依然会返回 HTTP 200。 每个响应都必须经过精确判定(正常、封禁、验证码、登录失效、条目已删、软 404),凡是无法明确判定的统一视作异常中断。
- 遇到验证码主动暂停,而非报错重试。扩展会停下来通知你, 你只需在常规标签页中完成验证(两者共享同一个登录会话),扩展通过轻量请求确认恢复后,会主动降低抓取频率继续执行。 在遭遇限流或软封禁时盲目重试,正是把临时限制恶化成永久封号的最常见原因。
- 登录状态一旦失效便立即停止任务,绝不盲目重试。
抓取不会失败,只会停下来
一次完整的全量抓取往往需要数小时,中途难免会遇到各种插曲:验证码、登录过期、网络波动,或者你想暂时关闭浏览器。 这些情况都不算故障。扩展每抓取一页就会立即落盘保存,因此无论中途停在何处, 在此之前抓到的每一页数据都已安全存入本地档案。
- 无论因为十几种原因中的哪一种停下来,已经抓到的内容都不会丢失。 验证码、软封锁、登录失效、断网、手动暂停、关闭浏览器——全部属于可恢复的暂停状态,下次打开点击「继续」就能接着走。 即使写入磁盘出错也不例外:修复机制始终向后截断,被截断的那条记录在续抓时会自动重新抓取,重复抓取并无额外成本。
- 中途停下的档案,解析器同样能够正常读取。
manifest.json虽然只在最终收尾时生成,未收尾的档案缺少该清单,但底层的页面和索引文件全都完整落盘, 其中每一条判定为「正常」的抓取都是真实有效的观测。标记、广播、作品、日记、豆列依然能照常解析。 - 导出到本地磁盘后,随时还能再导回扩展。 档案本身就是标准的普通文件夹。抓到一半导出的半成品,同样可以随时导回扩展继续执行断点续抓。
- 未完结的档案只是缺少证明「全部抓完」的连续性元数据,而非丢失了内容本身。 覆盖率与连续性证明只在最终收尾时写入,因此中途停止的档案无法作为下一次增量抓取的水位基准。所缺少的仅此而已。
- 个别页面确实可能无法成功获取——这是唯一一种真正的「失败」, 但它是逐页独立记录的:具体是哪几页、出于什么原因,都会单独列出。你可以选择重试,也可以确认按现状收尾; 受影响路线的水位线不会向前推进,下次增量依然会重新走完这一段。
因此「抓了一半」的档案千万不要随手删掉。 真正会导致数据永久遗失的操作只有一种:从未抓取。许多广播一旦被删便不留任何痕迹, 漏抓就是永久丢失——而已抓到的那一半,是极其珍贵且不可替代的。
它刻意不抓什么
备份的核心始终是属于你自己的个人数据。他人的内容不在采集范围内——这既是保护隐私的边界,也是明确的工程边界: 任何发散的社交关系都是无底洞。
| 不抓取 | 原因 |
|---|---|
| 他人发在你广播下的回复 | 属于外围社交互动。实测广播列表页只包含回复的容器结构与计数,并不包含正文,因此平时也不会顺带抓取到第三方内容。 |
| 关注、粉丝、黑名单列表 | 同上。关注列表指向的用户又各自拥有庞大的社交链,顺藤摸瓜将无穷无尽。 |
| 豆邮信箱 | 豆瓣收件箱中绝大多数内容是系统全站广播,真正有价值的极少部分往往被淹没在大量可替代的噪音之中。 |
| 他人的用户头像、CSS/JS 脚本及字体文件 | 不属于你的个人数据,也不影响归档内容的离线完整浏览。 |
如果日后打算将档案发布为公开网站,第三方内容默认会被剔除;在正式发布前,系统还会提供一次完整的明细预览,让你清晰了解究竟哪些内容会被公开。
现在能跑到什么程度
v1.0 已经发布。抓取流程已在真实豆瓣环境中全面跑通:
实测完成了一次 4 小时 16 分钟的全量抓取,累计 5880 条捕获记录,其中包含 2925 个作品详情页和 2918 张封面图,
全程零失败;八份连续成链的档案全部通过了规范校验。
不过,目前完整验证过的只有一个账号。该账号没有相册,日记也仅有三篇,许多分支尚未经受更多真实数据的检验。
此前发现的问题,几乎都是在尝试非典型流程时才暴露出来的(例如抓取中途重载扩展、或是开启「重抓作品详情页」)。
因此建议大家先将它作为「额外的容灾备份」,暂时不要作为唯一的依赖。
| 路线 | 状态 | 说明 |
|---|---|---|
| 广播 | ✅ 能跑 | 优先级最高:发出去就不能编辑,且删掉不留痕迹 |
| 标记列表(书/影视/音乐/游戏/舞台剧) | ✅ 能跑 | 看过/在看/想看,含标记日期与短评 |
| 作品详情页 | ✅ 能跑 | 由标记列表派生,含封面图;单独成段,不想要一条命令就能删 |
| 增量抓取 | ✅ 能跑 | 沿链回溯,标出改动与已失效的条目 |
| 导出与回读校验 | ✅ 能跑 | 整条链导出,每份各占一个子目录 |
| 日记 / 影评书评 | ✅ 能跑 | 列表页上只有截断的摘要,所以正文页单独抓一遍;两种日记 URL 形状都认 |
| 用户上传的图片 | ✅ 能跑 | 广播附图与日记正文内嵌图,只取本人上传的原图——转发进来的是别人的,不存 |
| 豆列 | ✅ 能跑 | 只抓自己编的。值钱的不是清单,是每个条目上自己写的评语——实测 134 个条目里 62 条有。私密豆列在生成的站点上带一把锁 |
| 个人相册 | ✅ 能跑 | 用户自建相册列表、相册内容与全尺寸原图;作品公共相册属于条目资产不予收录 |
| 豆瓣小组 | ✅ 能跑 | 小组主页、加入与管理的小组、本人发布的讨论列表、正文与上传附图;他人回帖不予收录 |
| 中断续导 | ✅ 能跑 | 导出被打断后再导一次,只补缺的那些;没有进度文件,目的地目录本身就是进度 |
| 解析成结构化数据 | ✅ 能跑 | 原始档案(bundle)→ 结构化数据(canonical):标记、作品、广播、长文、豆列、相册、小组,带修订历史 |
| 生成静态网站 | ✅ 能跑 | 结构化数据 → Markdown + 图片 → HTML,见样张 |
最缺的是别人的数据
到今天为止,这条链路只在一个账号上完整跑过。那个账号没有相册、 只有三篇日记、六个豆列。很多边界分支从来没被真实数据检验过—— 而豆瓣十几年里的页面结构差异,是坐在屋里凭空想不出来的: 本项目此前曾四次因为样本量过小而得出过错误结论 (最近这次是漏了一个图床域名)。
所以如果你愿意帮忙,按你能接受的程度挑一档就好。 第一档最有用,而且几乎没有隐私成本——绝大多数问题光靠它就能准确定位。
01 日志与覆盖率
面板「日志」页可以整份复制出来:抓过哪些 URL、重试、停机原因、错误。 里面没有你的短评、日记正文和图片。 覆盖率页那张表同样有用——尤其是「豆瓣声称 100 条、实际抓到 95 条」这种对不上的情况。
02 某一条路线的少量页面
如果你有很老的广播(2010 年前后的),那正是最缺乏样本的地方。个人自建相册与豆瓣小组现已完成实测支持。 豆列也还想要:已经做了,但只对着六份校准过,而它有好几种形态 (纯书签夹、几百条的大清单、条目是日记或广播的)。几页就够,不用给全部。
03 一整份档案
最有用,也最私密。发之前请先了解它装着什么:你的短评、
日记与影评全文、自己上传的图片原图、你的用户名,以及那些页面上的一切。
档案是普通文件,段可以整段删掉(catalog-* 是作品详情页,删了不影响其他)。
怎么发,以及会被怎么处理
- 能公开说的问题走 GitHub issue—— 首选,因为撞上同一个问题的人能看到。
- 涉及你自己数据的走邮件:[email protected]
- 收到的数据只用来修 bug 和补样本,不公开、不转给第三方; 你随时可以要求删掉,说一声就行。
- 永远不要发登录凭据。档案里没有 cookie,扩展也不会把它写进去。 如果有人以任何名义找你要豆瓣的 cookie 或密码,那不是我们。
还有一件不用交出任何数据、但一样有用的事: 告诉我们界面上有哪些文案引起了你的误解。 在这个项目里,「断言比实际事实更强」一律被视作 Bug 处理—— 此前把四次独立抓取误述为一条完整链条的问题就是这么发现的。
最近的开发日志
-
断点恢复只记下了未完成的,漏掉了已经抓过的
开跑后重载扩展,自动恢复的增量抓取把历史所有作品详情和封面重新抓了一遍。真凶是 checkpoint 为了紧凑只记了未完成队列,而把历史条目的跳过名单留在了上一次的内存里。顺带聊聊刚发布的 v1.5.0 与 v1.5.1:相册、小组,以及站点生成器的跟进。
-
同一张海报,换个服务器地址,档案里就多一条「改过」
111 条作品修订是凭空的,两版之间只差一个字符。而去修它之前先重量了当初记下的两个数字——两个都是错的,其中一个还把问题的性质说反了。
-
桌面浏览器放行了规范禁止的东西,于是那条路看起来是通的
安卓 Edge 上一按开始就抛出一句规范原文。是我上一版引入的:两条分支都用了动态加载,而只有一条需要——桌面 Chrome 开了口子,所以本机全绿、CI 全绿、真浏览器里跑得好好的。
项目由几个仓库组成
每个功能模块都可以独立查阅、审计和替换。 档案格式单独拆分为独立仓库并进行版本控制,因为这是整个链路中唯一一旦改错就无法补救的关键标准。
| 仓库 | 做什么 | 状态 |
|---|---|---|
| doubak-extension | 浏览器扩展。抓取,产出原始档案(bundle)。整个项目的入口都在这里。 | v1.5.1 |
| doubak-data-specs | 档案格式的规范文本与 JSON Schema。整个项目的基石。 | bundle 1.3 |
| doubak-data-parser | 原始档案 → 结构化数据(canonical)。纯函数,不联网。 | 能跑了 |
| doubak-site-generator | 结构化数据 → Markdown + 图片 → 有固定链接的个人存档站点。 | 能跑了 |
| doubak-site-generator-sample | 用作者自己的数据跑完整条流水线生成的样张,就是 sample.doubak.com。 | 在线 |
| doubak-export-adapters | 结构化数据 → NeoDB / Letterboxd / Goodreads 的导入文件。纯函数,不联网。 | 能跑了 |
| doubak-import-adapters | 别的抓取工具存下来的页面 → 原始档案(bundle)。于是那些旧数据能走完同一条流水线。 | 能跑了 |
此外还规划了 doubak-data-enricher(可选的外部链接补全)。 下游的所有处理模块都可以之后再慢慢实现,只要抓取已经完成——解析器本质上是对已抓取页面的纯函数转换,无论何时编写都不影响已存数据。 2020 年那一版 its-my-data/doubak(Go 命令行)目前已归档, 但当年抓取的历史档案并未白费:本项目的实测结论大多由那批数据验证得出,而现在借助 doubak-import-adapters 能把它们直接转成标准档案接纳进来——实测 782 MB、7353 个页面、2022 到 2024 年的四次抓取, 完整补回了 20 个月豆瓣自身已不保存的编辑历史。