简介:针对微博用户批量隐藏历史微博的 JavaScript 小工具,核心功能是把当前账号发布的微博一键设为“自己可见”,适合需要清理个人主页或保护隐私的普通用户,也适合前端开发者学习接口调用与 DOM 操作。压缩包共 3 个文件,包括 weibo-hide-all.js 主脚本、README 使用说明以及开源 LICENSE 协议,整体体量仅 6KB,轻量易部署。已有 760 人学习,拿到后可直接在 Chrome 登录微博并打开控制台执行,无需安装额外依赖;说明文档会交代基本用法,脚本本身也可作为分析微博页面交互的参考样本。通过简单几步即可完成批量隐藏操作,省去逐条手动设置的麻烦。 刚在微博上泡了快十年的账号,要说没点"黑历史"基本不可能。早期随手发的定位、加班吐槽、深夜emo,现在回头看每一条都让我血压升高。删吧,舍不得,毕竟那些都是自己真实的生活轨迹;不删吧,又怕被新认识的人翻个底朝天。所以我开始琢磨一件事:能不能把所有微博批量设置成"仅自己可见"?这就是 weibo-hide-all 这个项目最初的动机。
你要是也经历过"手动一条条点进每篇微博 → 右上角菜单 → 设为仅自己可见"这种机械劳动,应该能理解我为什么受不了。上千条微博,手动操作至少一晚上,还可能漏掉几条。这个项目的核心价值就一句话:一键把你全部已发微博批量设为"仅自己可见",解放双手的同时保住内容不丢失。
这篇文章我会把这个项目的整体设计、技术原理、代码思路和踩坑过程全部摊开讲。适合两类人看:一类是有微博内容清理需求、想直接抄作业的普通用户;另一类是对微博前端接口和浏览器自动化脚本感兴趣的开发者。不管属于哪种,我都会尽量用大白话把原理讲明白。
1. 项目核心需求与方案选型
1.1 需求拆解:不是删帖,是"降权可见"
这个项目要解决的并不是"从平台上删除内容",而是把内容从公开状态改成仅自己可见状态。这两种操作在平台机制里完全是两回事:删除是把微博从服务器上清掉,数据不可恢复;"仅自己可见"只是把微博的可见范围收缩到只有本人登录时才能看到,数据本身仍然在你的账号里。
为什么优先选择"仅自己可见"而不是批量删除?我从实际需求出发总结了几点:
- 数据保留:很多人的微博实际上是生活日志,"仅自己可见"相当于给日记本上了把锁,而不是把日记本烧掉。
- 操作可逆:万一哪天想通了,想重新公开某些内容,手动改回来就行;删了可就真的没了。
- 触发风控概率相对低:批量删除的异常行为特征往往更明显,而修改可见性的请求在单条操作上更接近正常用户行为。
- 心理负担小:面对上千条记录,一键锁起来比一键销毁来得轻松。
1.2 对"批量"要有一个量化概念
说"批量",到底要处理多少数据?我实际跑过一次,账号里有2600多条微博,其中有效公开状态的大概2400条。这个数量级决定了脚本的设计思路:如果是几十条,手动就行;一旦上千条,就必须考虑分页拉取、请求频率、失败重试和断点续跑。这已经不是一个简单循环能搞定的事,而是一个需要认真对待的小型自动化项目。
2. 技术实现的三种路线对比
动手之前,我先把实现方式过了一遍,也踩过一些弯路,这里直接把调研结果摆出来。
2.1 浏览器油猴脚本:最终选择
油猴脚本(Tampermonkey)运行在浏览器环境里,最大的天然优势是:你已经在网页上登录了微博,脚本可以直接复用页面上下文中的登录状态,不需要额外处理 Cookie 登录态。对于"一次性批量操作"这种需求,这是最轻量、最不容易出错的方式。
另外,油猴脚本可以直接在页面里发 fetch 请求,同域请求不存在跨域问题,接口返回的 JSON 也能直接解析。我把这个方案作为最终选择,后面实操部分会详细讲。
2.2 独立 Python 脚本:可行但维护成本高
Python + requests 是很多人首先想到的方案,它不依赖浏览器,适合放到服务器上定时跑。但问题在于,微博网页版接口的鉴权依赖登录后的 Cookie,而 Cookie 会因为过期、异地登录等原因失效。独立脚本除非先处理扫码登录或者手动拷贝 Cookie,否则很难稳定运行。
如果你实在想用 Python 实现,需要额外写登录态管理模块。但对我这种"只用一次、跑完就撤"的场景,Python 方案的维护成本明显高于浏览器脚本,所以放弃了。
2.3 RPA 模拟鼠标操作:最安全但效率太低
用按键精灵或 Playwright 之类的工具模拟真实点击,听起来最"无害",但实际体验很差。每条微博都要等页面渲染、等菜单弹出、再点确认,跑完2400条可能要四五个小时,中途页面一卡就前功尽弃。这个方案的唯一优势是"完全以用户身份操作",风控上最安全,但效率太低,只适合几十条的小规模处理。
3. 核心原理拆解:微博的可见性到底怎么改
这一节是整个项目的灵魂。搞清楚原理之后,代码只是顺带的事。
3.1 可见性字段不是你想的那么简单
微博的每条 content 对象里都有一个visible字段,它不只是"公开"或"私密"二值,而是一个包含多个参数的结构。实际抓包看到的大概长这样:
{ "id": "4999999999999999", "visible": { "type": 0, "list_id": 0 } }type是核心:0 表示公开,1 表示仅自己可见,还有其他值对应"仅粉丝可见""仅好友可见"等。修改可见性的本质,就是把这个字段的type从 0 改成 1。理解这一点后,整个项目就变成了一件很朴素的事:找到修改这个字段的接口,把每条微博的 ID 传进去。
3.2 分页拉取自己全部微博的接口
要修改所有微博,首先得有所有微博的 ID 列表。网页版微博在自己主页往下滚时,会不断触发一个接口,返回当前页的微博数组。这个接口按页拉取,需要你自己的 UID。以我当时抓到的路径为例:
https://weibo.com/ajax/statuses/mymblog?uid=你的UID&page=1每页返回约10条微博,响应结构里包含一个data.list数组,每条就是一篇微博的完整信息。翻页的终止条件是list为空数组,或者已经达到总页数。这里有个容易被忽略的细节:接口返回的list里可能混着"已删除"或"已隐藏"的占位记录,它们在后续修改时会报错,代码里要提前过滤掉非有效状态的数据。
3.3 修改可见性的请求:从抓包到复刻
我最开始并不知道修改可见性的接口长什么样,是打开浏览器开发者工具(F12),手动把一条微博设为"仅自己可见",然后在 Network 面板里找到那条 POST 请求,一步步还原出来的。这个方法值得所有想逆向微博接口的人掌握,因为平台改版是家常便饭,直接告诉你一个接口路径,过几天可能就失效了,但"抓包 → 复刻 → 验证"这个流程永远不会过时。
对于这个项目,核心修改请求的参数基本是微博 ID 和可见类型。我当时抓到的请求,表单里有id和visible两个关键字段,visible传对应"仅自己可见"的值,就完成了修改。不同时间平台参数结构会有变化,所以务必以你自己抓包的结果为准,不要照抄网上的代码。
4. 实操过程与核心代码解读
下面进入正题,我把整个脚本的落地过程按步骤拆开。完整代码我最终打成了一个油猴脚本,但这里更想分享核心逻辑,方便你根据自己的账号情况调整。
4.1 第一步:用浏览器开发者工具抓到修改接口
登录微博网页版,随便找一条自己发的微博,点右上角菜单里的"设为仅自己可见"。操作前先按 F12 打开开发者工具,切到 Network(网络)面板,确认记录是打开状态。操作完成后,在请求列表里筛选关键词,就能看到那条修改请求。
点开请求详情,记录三样信息:请求的完整 URL、请求方法是 GET 还是 POST、Form Data 或 Query String 里的参数名。我在实际操作中发现的规律是:修改可见性的接口是一条 POST 请求,参数以表单形式传递。拿到这些信息,后半段的代码就有了依据。
提示:不要省略这一步,也不要"凭感觉猜"接口。平台的参数名经常带随机后缀或语义化缩写,直接抓包最稳妥。
4.2 第二步:实现分页拉取全部微博 ID
拿到接口信息后,先写一个拉取函数,遍历自己的所有微博:
async function fetchAllPosts(uid) { const allPosts = []; let page = 1; while (true) { const url = `/ajax/statuses/mymblog?uid=${uid}&page=${page}`; const resp = await fetch(url); const data = await resp.json(); const list = data?.data?.list; if (!list || list.length === 0) break; allPosts.push(...list.map(p => ({ id: p.id, visibleType: p.visible?.type }))); page += 1; } return allPosts; }这段代码做了三件事:用page递增实现翻页;把每条微博的id和当前可见类型存下来;当接口返回空列表时终止循环。存visibleType是为了后续跳过已经私密的微博,避免重复请求。注意这里用了可选链写法(?.),如果接口结构变了,至少不会直接抛错,而是返回undefined,方便调试。
4.3 第三步:批量修改加频率控制
拉取完成后,核心循环就是对每条微博调用修改接口。这里最关键的不是代码本身,而是请求间隔和失败重试策略。我实测下来,如果请求间隔低于1秒,跑到三四十条的时候就可能触发平台风控,返回错误或者要求验证。比较稳妥的节奏是每条间隔1.5到2秒。
async function setAllPrivate(posts) { let success = 0, failed = 0, skipped = 0; for (const post of posts) { if (post.visibleType === 1) { skipped += 1; continue; } try { const resp = await fetch('/ajax/statuses/update', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `id=${post.id}&visible=1` }); const result = await resp.json(); if (result.ok === 1) { success += 1; } else { throw new Error(`接口返回异常: ${JSON.stringify(result)}`); } } catch (e) { failed += 1; console.error(post.id, e); } await new Promise(r => setTimeout(r, 1800)); } console.log(`完成: 成功${success},失败${failed},跳过${skipped}`); }注意两点:一是用try...catch包裹单条请求,并打印失败的微博 ID,这样脚本中途出错时能快速定位需要重跑的微博;二是把await new Promise放在循环末尾,保证每次请求之间都有固定间隔。
4.4 实际跑批的效果记录
我用自己的账号完整跑了一次,2400条需要处理的微博,按照1.8秒一条的间隔,总耗时约72分钟。中途没有任何请求失败,只有两条微博因为已是私密状态被跳过。整个过程不需要人工干预,但我的建议是不要开着脚本就去睡觉,最好人在电脑前,看到典型失败模式能及时暂停排查。
5. 常见问题与排查技巧实录
这个项目从开发到跑通,我记录了不少问题,整理成一张排查表,方便你直接对照。
5.1 报错与处理速查表
| 现象 | 可能原因 | 处理方法 |
|---|---|---|
| 请求返回未登录 | Cookie 失效或会话过期 | 刷新页面重新登录,再跑一次脚本 |
| 拉到空列表 | UID 传错或当前页面不是自己的主页 | 在个人主页 URL 里复制正确 UID |
| 个别微博修改报错 | 该微博已被删除或处于异常状态 | 记录 ID 跳过,最后单独手动处理 |
| 跑到一半要求验证码 | 请求频率过高触发风控 | 停半小时,继续时把间隔调到3秒以上 |
| 修改后页面仍显示公开 | 接口参数名变化 | 重新抓包确认参数名,替换脚本对应字段 |
这张表里的问题我都实际遇到过,尤其是验证码那个。第一次跑的时候没控制好节奏,直接触发了一次风险验证,导致整个任务中断。从那以后我就学乖了:宁可慢一点,也要把间隔时间调到安全区间。
5.2 只有踩过坑才知道的细节
最后分享三个我在开发过程中积累的经验。
第一个,操作前先做小规模验证。跑全量之前,先挑两三篇微博执行一遍修改逻辑,然后刷新个人主页确认它们真的变成了"仅自己可见"。这一步能在5分钟内排除90%的配置问题,千万不要跳过去。
第二个,日志比进度条重要。脚本不需要花哨的进度条,但一定要把每次成功、失败的微博 ID 记录到控制台。2400条微博跑到第1000条时突然报错,如果没有日志,你根本不知道从哪条继续。我自己的做法是跑之前先打开浏览器控制台的日志保存功能,跑完之后翻日志统计。
第三个,想好回滚方案。虽然"仅自己可见"不是删除,但如果你是为了把账号交给别人,或者以后想把内容重新公开,最好在操作前先把自己所有微博备份一遍。可以先随手保存重要内容,也可以借助微博本身的导出能力。别等到操作完成才发现需要一条旧数据,那时候就只能一篇篇找回来了。
根据我个人的实际体感,weibo-hide-all 这种"一次性自动化"脚本最大的价值不是省了多少时间,而是把"手动改上千条可见状态"这件繁琐到让人拖延的事情,压缩成了"装脚本 → 跑一次 → 完成"三步。如果你也有类似的微博历史内容清理需求,可以按我上面这套思路来:先抓包、再写循环、注意频率控制。过程不复杂,但每个细节都值得认真对待,尤其是节奏管理和日志记录这两件事,做好了基本不会翻车。
本文还有配套的精品资源,点击获取