简介:Octoman微博备份工具是一款基于JavaScript开发的新浪微博备份Chrome浏览器扩展,面向需要本地留存微博内容的个人用户,可解决微博易被删除、难以批量归档的问题。资源包内含20个文件,以js脚本、css样式、html页面及png图片为主,分别对应扩展逻辑、界面样式、弹窗页面与图标资源,整体仅134KB,轻量易部署。已有337人学习下载。通过该扩展,用户登录微博后即可选取目标博主,以每500条微博为一个HTML文件完成备份;所生成文件可用Chrome直接打开,并支持通过“另存为”方式转为完全离线版本,便于长期保存与查阅。对于需要留存个人微博、甚至处理异常账号内容的场景,这套工具提供了简洁可行的本地备份方案。
1. 微博备份不是收藏夹:为什么你需要一个本地快照工具
很多人以为点了收藏就等于留住了内容,直到某个深夜发现收藏夹里一片灰——原博删除、账号注销、关键词被清理,收藏列表变成一排失效链接。微博内容有很强的时效性和易失性,这决定了靠平台侧的收藏、点赞、转发都不算真正拥有。基于 JavaScript 实现的 Octoman 微博备份工具,做的就是把你自己的微博、评论、图片、视频链接从网页端接口拉下来,落成本地 JSON、图片文件和可检索的索引。适合需要长期留存自己发言记录、做内容资产沉淀,或者想对某段历史做完整快照的从业者。它不是爬全网数据的重型采集器,而是一个针对当前账号维度、按时间线增量导出的轻量工具。这篇笔记围绕它完整拆一遍——数据从哪来、怎么落地、参数怎么设、哪些坑是绕不过去的。
2. 从抓包到存储:Octoman 的备份链路与数据落盘设计
2.1 微博数据接口的常见形态与抓取边界
浏览器打开自己的微博主页,按 F12 切到 Network 面板,刷新页面后能看到一批 XHR 请求。Octoman 这类工具通常不会去模拟点击和滚动页面,而是直接请求微博网页端的 ajax 接口,最常见的是https://weibo.com/ajax/statuses/mymblog这类路径,它返回当前用户发布微博的 JSON 数据,字段里包含idstr、text、created_at、pic_ids、url_struct等信息。
抓取边界在于接口只返回“当前登录用户在网页端能看到的数据”。你去抓另一个人的主页,大概率会遇到权限校验或者返回空列表;抓自己已设置仅粉丝可见的内容也会受限。Octoman 的设计思路是“先满足本人账号备份”,而不是做一个万能采集器。它通过携带 Cookie 请求接口,把返回的 JSON 原样落盘,再抽取出纯文本、图片链接、视频链接做二次整理。
实际操作中,接口的since_id或max_id参数用来翻页。第一页返回的 JSON 里通常会带since_id,把它拿下来拼进下一次请求,持续循环直到返回的微博列表为空,就是全量抓完了。
2.2 备份数据的本地组织结构:JSON、图片与文本分离
Octoman 的落盘目录结构值得直接参考。根目录下通常分为raw、assets、index三个子目录,含义分别是原始 JSON、二进制图片文件、可读性更好的索引文件。每一次运行备份,raw目录里按当天日期生成一个文件夹,保存该次请求拿到的原始响应;assets目录按微博 id 建立子目录,存放该微博下的图片文件;index目录则存放经过清洗后的 Markdown 或 HTML 文件,方便人直接阅读。
我一般会在配置里指定backupDir为绝对路径,避免相对路径在不同系统下翻车。一个典型的目录结构长得像下面这样:
backupDir ├── raw/2025-04-10/xxx.json ├── assets/WB001/001.jpg ├── assets/WB001/002.jpg └── index/2025-04-10.md这种 JSON、图片、索引分离的结构有实际好处:原始 JSON 是黑匣子级别的保底数据,就算后续索引生成逻辑写错了,还能重新解析 raw 文件找回内容;图片单独存放则方便做对象存储迁移或本地相册归档。index目录下的 Markdown 文件可以直接被 Obsidian、Typora 这类工具打开,搜索和阅读体验远好于直接翻 JSON。
2.3 增量备份与去重:不把时间浪费在已备份的内容上
第一次全量备份很顺利,问题出在第二次跑的时候——如果每次都把全部微博重新下载,图片资源和接口请求量都会成倍浪费。Octoman 的去重逻辑通常是依赖微博 id 来做的,每条微博有全局唯一的idstr,本地已经存在的 id 就跳过,只抓上次备份之后新增的内容。
这个去重策略有个隐含前提:本地必须已经保存了 id 列表。所以我建议把备份产物的索引文件当作“数据库”来看待,不要随便删。增量备份时会先扫描index目录下已有的 id 集合,再和接口返回的第一页数据比对,找到最大 id 或最早时间点作为断点参考。
断点续传也是这一层要考虑的事。如果备份到一半网络断了,重启后 Octoman 会重新从第一页开始请求,但已经落盘的图片不会重复下载,因为本地文件系统里已经有对应 id 的文件了。这个设计比较朴素,但胜在可靠——以文件是否存在作为是否下载过的判断依据,不做额外的状态记录文件,反而减少了状态不一致的问题。
3. 把备份跑起来:环境初始化、参数配置与首次全量导出
3.1 依赖准备:JavaScript 运行时环境与项目初始化
Octoman 是基于 JavaScript 写的,所以第一步是准备 Node.js 运行环境。建议使用 Node 16 以上的版本,因为代码里可能用到了fetch、AbortController这些较新的 API,老版本的 Node 不内置这些能力,跑起来会报fetch is not defined。检查环境用下面两条命令:
node -v npm -v输出里如果版本号低于预期,建议先去官网装 LTS 版本。项目初始化的过程是把 Octoman 的源码包解压到目标目录,然后执行依赖安装:
cd octoman-weibo-backup npm install这里的npm install会读取package.json里的依赖列表,把需要的库装到node_modules里。常见依赖包括axios(网络请求)、cheerio(HTML 解析)、commander(命令行参数处理)等。装完之后可以看下package.json里的scripts字段,确认启动命令是npm run start还是node src/index.js,不同版本的入口可能不一样。
参数配置方面,Octoman 通常会提供一个.env或config.js文件,里面最关键的三项是 Cookie、备份目录路径、请求间隔时间。Cookie 从浏览器登录微博后复制,注意要复制完整的 Cookie 字符串,只复制半截的SINA开头字段会导致鉴权失败。
3.2 首次全量备份:登录态、间隔参数与导出格式
准备工作做完后,首次备份建议先跑一小段验证链路通不通,不要一上来就全量。可以先在命令行里加一个--limit 10这样的参数,限制只抓取最近 10 条微博:
node src/index.js --cookie "你的完整Cookie" --limit 10跑通后,再执行完整备份命令。注意控制请求频率,微博接口对高频请求的封禁策略非常敏感。常见做法是在配置里设置interval为 800 到 1500 毫秒,也就是每抓一页休息约一秒。短于 500 毫秒的请求节奏非常容易触发风控,表现为接口突然返回1005或-100之类的错误码。如果备份的微博数量大、图片多,建议把interval调大到 2000 毫秒,时间换安全性,完全值得。
导出格式方面,Octoman 默认输出 JSON 和 Markdown 两种。JSON 保留接口原始字段,Markdown 则适合阅读和二次编辑。如果你后续打算把备份内容导入其他笔记软件,建议保留 Markdown 格式,它比 JSON 可读性好,而且纯文本文件在做全文检索时相对友好。
3.3 备份产物校验:从目录结构反查完整性
备份跑完后,不要急着关终端,先做一轮产物完整性检查。我会习惯性地在index目录下随机挑几天的 Markdown 文件,核对里面的微博条数和页面显示的数量是否一致。更彻底的方式是统计raw目录下 JSON 文件的数量和日期覆盖范围:
find backupDir/raw -name "*.json" | wc -l find backupDir/raw -type d | sort | tail -5第一条命令统计所有原始响应文件的数量,第二条查看最近生成的日期文件夹。如果日期文件夹能连续覆盖到当天,说明翻页逻辑没有中途卡死;如果某个日期缺失,就要考虑是不是网络问题导致那一段的请求直接失败了。还有一个小技巧——检查assets目录下图片子目录的数量是否接近微博总数。图片是二进制文件,下载过程中如果断了不会自动修复,文件数量对不上基本就是漏图了。
4. 微博备份避坑指南:登录态失效、频率限制与缺失数据
4.1 Cookie 过期导致批量失败:现象是存档期突然出现大量 404 和空文件
运行备份跑了一段时间,某天突然发现输出里连续出现“请求失败”和-100错误,之前一直好好的。打开浏览器登录微博,发现网页版需要重新扫码登录——这就是会话过期了。微博网页端的 Cookie 有效期不定,短则几天长则几周,跟账号活跃度和风控状态有关。
解决办法是做好 Cookie 失效的预警检测。Octoman 在请求接口后如果连续返回 3 次鉴权类错误码,我会在脚本外面包一层日志监控,检测到-100就停止任务并发送提醒。另外建议养成每周手动更新一次 Cookie 的习惯,脚本每次启动前先读取最新 Cookie,保持配置文件里的值始终是最近一次登录后复制的。
4.2 接口频率限制:现象是备份卡在某一页反复重试
备份跑到一半,日志显示同一页被请求了七八次,每次返回的都是错误码。这就是接口频率触发限制的典型表现。微博网页端接口的限流阈值没有公开文档说明,从血泪经验来看,低于 500 毫秒的单次间隔基本必被限,连续请求超过 2000 次也有概率被临时封禁。
解决方向是两个:一是调大interval到 1500 毫秒以上;二是在请求失败时做指数退避重试,第一次失败等 5 秒、第二次等 10 秒、第三次等 20 秒,累计失败超过 5 次就暂停该轮备份。把这段逻辑写进配置文件,让它自动执行,不要手动盯着终端反复重跑。
4.3 图片延迟加载导致空文件:现象是 assets 目录里出现 0 字节图片
微博的图片链接是懒加载的,接口返回的pic_ids只给了图片 ID,真实地址需要拼接https://wx1.sinaimg.cn/large/{id}.jpg这样的 URL 才能访问。有些时候接口返回的图片地址是https://wx1.sinaimg.cn/mw690/{id}.jpg,但mw690是压缩图,原图对应的后缀是large。如果脚本直接拿接口里的地址下载,下载到一半服务端返回 302 跳转,跳转链路断了就会落盘一个空文件。
解决方法是下载图片时先检查响应头的Content-Length,小于 1024 字节就认定为下载异常,重新请求一次。另外在拼 URL 时使用large后缀而不是mw690,能在多数情况下直接取到原图。如果原图下载失败但压缩图存在,脚本应当降级保存压缩图,而不是报错中断。
4.4 转发微博的正文内容重复:现象是搜索时同一段文字出现多次
微博转发时,原博的文字内容会出现在被转发微博的text字段里,如果你既转发了原博又评论了一句话,备份下来的内容可能包含两段重复的原文。这是微博接口返回数据的特性,不是工具写错了。
处理方式是解析text字段时单独提取“转发者自己的话”和“原博内容”两部分,分开存到不同字段。Markdown 导出时用分隔线把两部分隔开,这样检索时能精确命中你写的评论,而不是每次搜到一堆重复的原文。还有一种情况是原博已被删除,但转发记录还在,此时retweeted_status字段为空,直接展示“原博已删除”占位文本即可,不要强行拼 URL。
4.5 备份中途停机会产生“假完成”:现象是时间线中间缺了一片内容
有一次备份跑到一半笔记本没电关机了,重启后继续跑,看到日志显示“备份完成”,但翻index目录发现中间某个月份的记录整段缺失。原因是该轮备份有断点续传逻辑,但它判断“已备份”的条件是”存在it返回值对应的索引目录“,而中途停止的会话里,索引文件只写了一半,没有写入最后一行结束标记。
解决方法是每次备份完成后,生成一个summary.json文件,里面写入本轮开始时间、结束时间、抓取的微博总数、图片总数。下次备份开始前先检查summary.json是否存在且结束时间不为空,如果发现上一轮没有结束标记,就强制做一次全量校验,而不是直接跳到增量流程。
5. 从备份到检索:用导出的 JSON 做本地内容过滤与二次加工
5.1 把 JSON 转成结构化表格:用脚本提取发布时间、正文与图片数
原始 JSON 文件的字段非常冗长,直接扔进 Excel 或者数据库之前,要先做一轮字段抽取。常见做法是写一个 Node.js 脚本,遍历raw目录里所有 JSON 文件,提取每条微博的idstr、created_at、text_raw、pic_num、reposts_count、comments_count等核心字段,输出成 CSV 或者 SQLite 表。
示例脚本片段如下,核心逻辑是递归读取所有 JSON 文件并平铺成对象数组:
const fs = require('fs'); const path = require('path'); function walkDir(dir) { const results = []; for (const file of fs.readdirSync(dir)) { const full = path.join(dir, file); if (fs.statSync(full).isDirectory()) { results.push(...walkDir(full)); } else if (file.endsWith('.json')) { results.push(full); } } return results; } function extractList(rawDir) { const list = []; for (const file of walkDir(rawDir)) { const data = JSON.parse(fs.readFileSync(file, 'utf8')); if (!data.data || !Array.isArray(data.data.list)) continue; for (const item of data.data.list) { list.push({ id: item.idstr, time: item.created_at, text: item.text_raw || item.text, pics: (item.pic_ids || []).length }); } } return list; } const rows = extractList('backupDir/raw'); console.log(`共提取 ${rows.length} 条微博`); fs.writeFileSync('backup.csv', rows.map(r => `${r.id},${r.time},${r.text.replace(/,/g, ',')},${r.pics}` ).join('\n'));这段代码有两个关键设计:walkDir递归遍历目录,保证了多天备份的 JSON 文件都能被扫到;text_raw优先于text,因为text字段里往往混着 HTML 标签,而text_raw是纯文本。如果你后续要做词频分析或情感分析,建议直接用text_raw作为输入。
5.2 本地全文搜索:不依赖平台的轻量索引方案
备份完成后最常用的操作是搜索——搜某年发过的某条内容、搜某个关键词和谁的互动。数据量不大的时候,直接用 Node.js 的fs模块逐行扫描就是最朴素的方案。但如果内容有几千条,每次搜索都全量遍历就会有点慢,可以建一个简单的倒排索引。
索引结构按关键词建 Map,每个关键词对应一组微博 id:
const idx = new Map(); for (const item of rows) { const words = item.text.split(/[\s,。!?、]/); for (const w of words) { if (w.length < 2) continue; if (!idx.has(w)) idx.set(w, new Set()); idx.get(w).add(item.id); } } function search(keyword) { const ids = idx.get(keyword); if (!ids) return []; return rows.filter(r => ids.has(r.id)); }这个实现里用 Set 去重,避免同一单词在同一微博出现多次导致重复命中;w.length < 2过滤掉单字噪声,减少索引体积。如果想更省事,也可以把备份数据导入 SQLite,用LIKE '%关键词%'查询,效果差不多,索引空间也小得多。对于个人备份场景,我自己更偏向 SQLite 方案——不用维护内存索引,查询语法也更通用。
5.3 生成可读的 HTML 归档:把备份变成能直接翻阅的存档站
JSON 和 Markdown 适合程序处理,但给不熟悉技术的人翻阅时,HTML 归档体验更好。我可以写一个生成脚本,把每条微博渲染成类似网页时间线的结构,按月份分组,微博卡片里放正文、图片缩略图、发布时间和转发评论数。这样的归档可以直接用浏览器打开,也能扔到任意静态站点服务器上。
生成 HTML 时的关键点是处理图片路径——备份下来的图片在assets目录,HTML 文件如果放在别的位置,引用图片时要算相对路径。常见做法是在 HTML 的<img>标签里写../assets/WBxxx/001.jpg,保证整个归档目录移动后依然能显示图片。生成完以后用浏览器打开首页,随机点几个月份检查图片是否正常加载。
6. 让备份变成每周的习惯:定时任务、资源占用与一条命令跑完
备份工具能跑通只是第一步,真正有价值的是把它变成长期习惯。我现在的做法是用系统自带的定时任务每周日凌晨三点跑一次增量备份,命令是node src/index.js --cookie "$(cat .cookie)" --interval 1500。运行前先读取.cookie文件里的最新 Cookie,避免把敏感字符串直接嵌到脚本里。日志输出重定向到backup.log,这样每次运行后只需要检查日志末尾有没有“备份完成”字样。
资源占用方面,增量备份比全量备份轻得多。实测每周跑一次、每次新增几十条微博和十几张图片,内存占用约 200MB,时间在几分钟内完成;全量备份首次跑会占用较多带宽和 CPU,建议在夜间执行。另外一个值得做的动作是给backupDir目录做一次 git 初始化,每次备份完成后自动提交一次,这样内容有任何变化都有痕迹可追。
还有个小技巧——拿备份数据做月度统计。每周备份后把 JSON 里的created_at字段按月聚合,统计发博频率、图片数量、关键词趋势。这个方法让我对内容产出的规律有了特别直观的认识。从那以后我每次跑完备份都会顺手看一眼summary.json,确认三条信息:新增条数、图片下载成功率、是否有鉴权报错。这三项正常,这一轮备份就是健康的。说到底,备份工具的意义不是跑一次,而是能长期稳定地跑下去,希望这套思路能帮到你。
本文还有配套的精品资源,点击获取