
HY
折腾进行时
Hello, I'm HY.








暂未播放

B站没有批量修改稿件可见性的功能。如果你有一百多个视频想全部设成”仅自己可见”,一个一个手动点编辑 → 更多设置 → 仅自己可见 → 提交,手都得废。
这个脚本就是干这件事的。脚本用 ZCode 配合商汤的 DeepSeek V4 Flash 模型辅助开发,最终版本稳定跑完 127 个视频。
我在127个视频上实测过,最终结果:
如果你还没装 Tampermonkey,先装一个:
把下面的代码复制一下:
1// ==UserScript==2// @name B站批量隐藏投稿3// @namespace https://bilibili.com/4// @version 9.0.05// @description 批量将B站稿件设置为"仅自己可见",支持自定义起止页,自动翻页6// @match https://member.bilibili.com/platform/upload-manager/article*7// @match https://member.bilibili.com/platform/upload/video/frame*8// @grant none9// ==/UserScript==10
11(function () {12 'use strict';13
14 const ST = 'bili_batch_hide_v9';15 const QU = 'bili_batch_hide_queue_v9';16 const LIST_URL = 'https://member.bilibili.com/platform/upload-manager/article';17 const eUrl = b => 'https://member.bilibili.com/platform/upload/video/frame?type=edit&bvid=' + b;18 const slp = ms => new Promise(r => setTimeout(r, ms));19
20 function gs() { try { return JSON.parse(localStorage.getItem(ST)); } catch (e) { return null; } }21 function ss(s) { localStorage.setItem(ST, JSON.stringify(s)); }22 function cs() { localStorage.removeItem(ST); localStorage.removeItem(QU); }23 function gq() { try { return JSON.parse(localStorage.getItem(QU)) || []; } catch (e) { return []; } }24 function sq(q) { localStorage.setItem(QU, JSON.stringify(q)); }25
26 function curPg() {27 const m = location.href.match(/[?&]page=(\d+)/);28 return m ? parseInt(m[1]) : 1;29 }30 function isLP() { return location.href.includes('/upload-manager/article'); }31 function isEP() { return location.href.includes('/upload/video/frame'); }32
33 function collect() {34 const links = document.querySelectorAll('a[href*="/video/BV"]');35 const seen = new Set();36 const q = [];37 let sk = 0;38 links.forEach(a => {39 const m = a.href.match(/\/video\/(BV[a-zA-Z0-9]+)/);40 if (!m || seen.has(m[1])) return;41 seen.add(m[1]);42 const row = a.closest('li, div, [class*="item"]');43 if (row && row.textContent.includes('仅自己可见')) sk++;44 else q.push(m[1]);45 });46 return { queue: [...new Set(q)], skipped: sk };47 }48
49 function mkPanel() {50 if (document.getElementById('bs-panel')) return;51 const p = document.createElement('div');52 p.id = 'bs-panel';53 p.style.cssText = `54 position: fixed; z-index: 999999; right: 20px; top: 100px;55 width: 270px; padding: 15px; background: #18191c; color: #fff;56 border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,.35);57 font-size: 14px; font-family: Arial, sans-serif;58 `;59 p.innerHTML = `60 <div style="font-size:16px;font-weight:bold;margin-bottom:10px;">B站批量隐藏</div>61 <div id="bs-cur" style="margin-bottom:6px;color:#aaa;">当前页:第 ${curPg()} 页</div>62 <div id="bs-st" style="margin-bottom:10px;">状态:等待开始</div>63 <div id="bs-cnt" style="margin-bottom:12px;">已处理:0 跳过:0 失败:0</div>64 <div style="margin-bottom:8px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;">65 <span style="font-size:12px;color:#aaa;">从第</span>66 <input id="bs-sp" type="number" min="1" max="99" value="1"67 style="width:45px;padding:4px;border:1px solid #555;border-radius:4px;background:#2a2a2a;color:#fff;text-align:center;font-size:13px;">68 <span style="font-size:12px;color:#aaa;">页到第</span>69 <input id="bs-ep" type="number" min="1" max="99" value="99"70 style="width:45px;padding:4px;border:1px solid #555;border-radius:4px;background:#2a2a2a;color:#fff;text-align:center;font-size:13px;">71 <span style="font-size:12px;color:#aaa;">页</span>72 </div>73 <button id="bs-go" style="width:100%;padding:8px;border:0;border-radius:6px;74 background:#00aeec;color:#fff;cursor:pointer;margin-bottom:6px;">开始批量隐藏</button>75 <button id="bs-stp" style="width:100%;padding:8px;border:0;border-radius:6px;76 background:#444;color:#fff;cursor:pointer;margin-bottom:6px;">停止</button>77 <button id="bs-rst" style="width:100%;padding:6px;border:0;border-radius:6px;78 background:#333;color:#aaa;cursor:pointer;font-size:12px;">重置状态</button>79 <div style="margin-top:10px;color:#aaa;font-size:12px;line-height:1.5;">80 自动翻页处理到结束页。<br>已"仅自己可见"的自动跳过。<br>面板在列表页和编辑页都会显示。81 </div>82 `;83 document.body.appendChild(p);84
85 const sp = localStorage.getItem('bs_sp');86 const ep = localStorage.getItem('bs_ep');87 if (sp) document.getElementById('bs-sp').value = sp;88 if (ep) document.getElementById('bs-ep').value = ep;89
90 document.getElementById('bs-sp').onchange = () => localStorage.setItem('bs_sp', document.getElementById('bs-sp').value);91 document.getElementById('bs-ep').onchange = () => localStorage.setItem('bs_ep', document.getElementById('bs-ep').value);92
93 document.getElementById('bs-go').onclick = function () {94 if (gs() && gs().running) { stUI('运行中,请先停止'); return; }95 const sp = Math.max(1, parseInt(document.getElementById('bs-sp').value) || 1);96 const ep = Math.max(sp, parseInt(document.getElementById('bs-ep').value) || 99);97 cs();98 ss({99 running: true, collected: false, reachedStart: false,100 processed: 0, skipped: 0, failed: 0, queue: [],101 startPage: sp, endPage: ep, currentPage: 0, done: false102 });103 sq([]);104 localStorage.setItem('bs_sp', String(sp));105 localStorage.setItem('bs_ep', String(ep));106 stUI('开始(第 ' + sp + '~' + ep + ' 页)');107 location.href = LIST_URL + (sp > 1 ? '?page=' + sp : '');108 };109
110 document.getElementById('bs-stp').onclick = () => { cs(); stUI('已停止'); updP(); };111 document.getElementById('bs-rst').onclick = () => { cs(); stUI('已重置'); updP(); };112 }113
114 function updP() {115 const s = gs();116 const el = document.getElementById('bs-cnt');117 const pel = document.getElementById('bs-cur');118 if (el && s) el.textContent = '已处理:' + (s.processed || 0) + ' 跳过:' + (s.skipped || 0) + ' 失败:' + (s.failed || 0);119 else if (el) el.textContent = '已处理:0 跳过:0 失败:0';120 if (pel) pel.textContent = '当前页:第 ' + curPg() + ' 页(目标 ' + (s ? s.startPage + '~' + s.endPage : '-') + ')';121 }122 function stUI(t) { const el = document.getElementById('bs-st'); if (el) el.textContent = '状态:' + t; }123
124 function advance() {125 const s = gs();126 if (!s || !s.running || !isLP()) return;127 if (s.done) return;128
129 s.currentPage = curPg();130 ss(s);131 updP();132
133 if (!s.reachedStart) {134 if (curPg() < s.startPage) {135 stUI('跳转到第 ' + s.startPage + ' 页...');136 location.href = LIST_URL + '?page=' + s.startPage;137 return;138 }139 s.reachedStart = true;140 ss(s);141 }142
143 if (curPg() > s.endPage) { finish(); return; }144
145 if (!s.collected) {146 const { queue, skipped } = collect();147 if (queue.length === 0 && document.querySelectorAll('a[href*="/video/BV"]').length === 0) {148 stUI('等待页面加载...');149 setTimeout(() => { if (gs() && gs().running && !gs().done) advance(); }, 2000);150 return;151 }152 s.skipped = (s.skipped || 0) + skipped;153 s.queue = queue;154 s.collected = true;155 ss(s);156 sq(queue);157
158 if (queue.length === 0) {159 stUI('本页无待处理,进入下一页');160 s.collected = false; ss(s); nextPage();161 return;162 }163 goEdit();164 return;165 }166
167 if (s.queue.length > 0) { goEdit(); return; }168 s.collected = false; ss(s); nextPage();169 }170
171 function goEdit() {172 const s = gs();173 if (!s || !s.running) return;174 if (!s.queue || s.queue.length === 0) { advance(); return; }175 const next = s.queue.shift();176 sq(s.queue);177 ss(s);178 stUI('处理 ' + next + ' | 第 ' + s.currentPage + '/' + s.endPage + ' 页');179 location.href = eUrl(next);180 }181
182 function nextPage() {183 const s = gs();184 if (!s || !s.running || s.done) return;185 if (curPg() >= s.endPage) { finish(); return; }186 stUI('进入第 ' + (curPg() + 1) + ' 页...');187 s.collected = false; ss(s);188 location.href = LIST_URL + '?page=' + (curPg() + 1);189 }190
191 function finish() {192 const s = gs(); if (!s) return;193 s.done = true; ss(s);194 const msg = '🎉 全部完成!\n处理:' + (s.processed || 0) + ',跳过:' + (s.skipped || 0) + ',失败:' + (s.failed || 0);195 alert(msg); cs(); stUI('全部完成');196 }197
198 async function handleEP() {199 const s = gs();200 if (!s || !s.running || s.done) return;201 updP(); stUI('正在编辑...');202 await slp(2000);203
204 let ok = false, clicked = false;205 const labels = document.querySelectorAll('span.label');206 for (const l of labels) { if (l.textContent.trim().startsWith('更多设置')) { l.click(); clicked = true; break; } }207 if (!clicked) {208 const titles = document.querySelectorAll('div.title');209 for (const t of titles) { if (t.textContent.trim().startsWith('更多设置')) { t.click(); clicked = true; break; } }210 }211 if (!clicked) {212 const all = document.querySelectorAll('span, div, a');213 for (const e of all) { if (e.textContent.trim().startsWith('更多设置')) { e.click(); clicked = true; break; } }214 }215
216 if (clicked) {217 await slp(1200);218 const containers = document.querySelectorAll('.check-radio-v2-container');219 if (containers.length >= 2) {220 const isChecked = containers[1].querySelector('.check-radio-v2-box-checked') !== null;221 if (!isChecked) {222 const radio = containers[1].querySelector('.check-radio-v2-box, span');223 if (radio) radio.click(); else containers[1].click();224 await slp(800);225 }226 const sub = document.querySelector('span.submit-add');227 if (sub) { sub.click(); ok = true; }228 else {229 const all = document.querySelectorAll('div, button, span');230 for (const e of all) { if (e.textContent.trim() === '立即投稿') { e.click(); ok = true; break; } }231 }232 }233 }234
235 const st = gs();236 if (st) { if (ok) st.processed = (st.processed || 0) + 1; else st.failed = (st.failed || 0) + 1; ss(st); }237 updP();238 stUI(ok ? '已提交,返回列表...' : '失败,返回列表...');239 await slp(2500);240 const st2 = gs();241 const pg = st2 && st2.currentPage ? st2.currentPage : 1;242 location.href = LIST_URL + (pg > 1 ? '?page=' + pg : '');243 }244
245 setTimeout(function () { mkPanel(); updP(); }, 500);246
247 if (isLP()) {248 setTimeout(function () {249 const s = gs();250 if (s && s.running && !s.done) { stUI('自动继续...'); updP(); advance(); updP(); }251 }, 2000);252 }253
254 if (isEP()) { handleEP(); }255})();在浏览器中打开 B站创作中心 → 稿件管理
页面右上角会出现一个黑色的控制面板:
点完按钮后,脚本会自动:
面板会一直显示在页面右上角,无论是在列表页还是编辑页都能看到:
点击 “停止” 按钮即可。之后想继续,回到列表页设置好起止页数,再点”开始”就行。
说起来其实很简单:脚本在列表页收集所有视频的BV ID,逐个跳转到编辑页,自动展开”更多设置”→ 选中”仅自己可见”→ 提交,然后回到列表页取下一条。翻页是通过直接跳转URL实现的,比依赖SPA的”下一页”按钮要稳定得多。
全程大概就是这个流程:
1列表页收集BV ID → 跳转编辑页 → 展开更多设置 → 选仅自己可见 → 提交 → 回列表页 → 下一个2 ↓3 本页完成 → 翻页到下一页如果你有批量处理B站视频的需求,这个脚本应该能帮你省不少时间。用之前记得先备份,毕竟批量操作出了错不太好恢复。
最后再分享一个设置为公开可见的脚本,直接叫我的zcode+dsv4f在上面的基础直接改的
1// ==UserScript==2// @name B站批量公开投稿3// @namespace https://bilibili.com/4// @version 1.0.05// @description 批量将B站稿件设置为"公开可见",支持自定义起止页,自动翻页6// @match https://member.bilibili.com/platform/upload-manager/article*7// @match https://member.bilibili.com/platform/upload/video/frame*8// @grant none9// ==/UserScript==10
11(function () {12 'use strict';13
14 const ST = 'bili_batch_public_v1';15 const QU = 'bili_batch_public_queue_v1';16 const LIST_URL = 'https://member.bilibili.com/platform/upload-manager/article';17 const eUrl = b => 'https://member.bilibili.com/platform/upload/video/frame?type=edit&bvid=' + b;18 const slp = ms => new Promise(r => setTimeout(r, ms));19
20 function gs() { try { return JSON.parse(localStorage.getItem(ST)); } catch (e) { return null; } }21 function ss(s) { localStorage.setItem(ST, JSON.stringify(s)); }22 function cs() { localStorage.removeItem(ST); localStorage.removeItem(QU); }23 function gq() { try { return JSON.parse(localStorage.getItem(QU)) || []; } catch (e) { return []; } }24 function sq(q) { localStorage.setItem(QU, JSON.stringify(q)); }25
26 function curPg() {27 const m = location.href.match(/[?&]page=(\d+)/);28 return m ? parseInt(m[1]) : 1;29 }30 function isLP() { return location.href.includes('/upload-manager/article'); }31 function isEP() { return location.href.includes('/upload/video/frame'); }32
33 function collect() {34 const links = document.querySelectorAll('a[href*="/video/BV"]');35 const seen = new Set();36 const q = [];37 let sk = 0;38 links.forEach(a => {39 const m = a.href.match(/\/video\/(BV[a-zA-Z0-9]+)/);40 if (!m || seen.has(m[1])) return;41 seen.add(m[1]);42 const row = a.closest('li, div, [class*="item"]');43 // 跳过已经是公开的(没有"仅自己可见"标记的视为公开)44 if (row && !row.textContent.includes('仅自己可见')) sk++;45 else q.push(m[1]);46 });47 return { queue: [...new Set(q)], skipped: sk };48 }49
50 function mkPanel() {51 if (document.getElementById('bs-panel')) return;52 const p = document.createElement('div');53 p.id = 'bs-panel';54 p.style.cssText = `55 position: fixed; z-index: 999999; right: 20px; top: 100px;56 width: 270px; padding: 15px; background: #18191c; color: #fff;57 border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,.35);58 font-size: 14px; font-family: Arial, sans-serif;59 `;60 p.innerHTML = `61 <div style="font-size:16px;font-weight:bold;margin-bottom:10px;">B站批量公开</div>62 <div id="bs-cur" style="margin-bottom:6px;color:#aaa;">当前页:第 ${curPg()} 页</div>63 <div id="bs-st" style="margin-bottom:10px;">状态:等待开始</div>64 <div id="bs-cnt" style="margin-bottom:12px;">已公开:0 跳过:0 失败:0</div>65 <div style="margin-bottom:8px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;">66 <span style="font-size:12px;color:#aaa;">从第</span>67 <input id="bs-sp" type="number" min="1" max="99" value="1"68 style="width:45px;padding:4px;border:1px solid #555;border-radius:4px;background:#2a2a2a;color:#fff;text-align:center;font-size:13px;">69 <span style="font-size:12px;color:#aaa;">页到第</span>70 <input id="bs-ep" type="number" min="1" max="99" value="99"71 style="width:45px;padding:4px;border:1px solid #555;border-radius:4px;background:#2a2a2a;color:#fff;text-align:center;font-size:13px;">72 <span style="font-size:12px;color:#aaa;">页</span>73 </div>74 <button id="bs-go" style="width:100%;padding:8px;border:0;border-radius:6px;75 background:#00aeec;color:#fff;cursor:pointer;margin-bottom:6px;">开始批量公开</button>76 <button id="bs-stp" style="width:100%;padding:8px;border:0;border-radius:6px;77 background:#444;color:#fff;cursor:pointer;margin-bottom:6px;">停止</button>78 <button id="bs-rst" style="width:100%;padding:6px;border:0;border-radius:6px;79 background:#333;color:#aaa;cursor:pointer;font-size:12px;">重置状态</button>80 <div style="margin-top:10px;color:#aaa;font-size:12px;line-height:1.5;">81 自动翻页处理到结束页。<br>已公开的自动跳过。<br>面板在列表页和编辑页都会显示。82 </div>83 `;84 document.body.appendChild(p);85
86 const sp = localStorage.getItem('bs_sp');87 const ep = localStorage.getItem('bs_ep');88 if (sp) document.getElementById('bs-sp').value = sp;89 if (ep) document.getElementById('bs-ep').value = ep;90
91 document.getElementById('bs-sp').onchange = () => localStorage.setItem('bs_sp', document.getElementById('bs-sp').value);92 document.getElementById('bs-ep').onchange = () => localStorage.setItem('bs_ep', document.getElementById('bs-ep').value);93
94 document.getElementById('bs-go').onclick = function () {95 if (gs() && gs().running) { stUI('运行中,请先停止'); return; }96 const sp = Math.max(1, parseInt(document.getElementById('bs-sp').value) || 1);97 const ep = Math.max(sp, parseInt(document.getElementById('bs-ep').value) || 99);98 cs();99 ss({100 running: true, collected: false, reachedStart: false,101 processed: 0, skipped: 0, failed: 0, queue: [],102 startPage: sp, endPage: ep, currentPage: 0, done: false103 });104 sq([]);105 localStorage.setItem('bs_sp', String(sp));106 localStorage.setItem('bs_ep', String(ep));107 stUI('开始(第 ' + sp + '~' + ep + ' 页)');108 location.href = LIST_URL + (sp > 1 ? '?page=' + sp : '');109 };110
111 document.getElementById('bs-stp').onclick = () => { cs(); stUI('已停止'); updP(); };112 document.getElementById('bs-rst').onclick = () => { cs(); stUI('已重置'); updP(); };113 }114
115 function updP() {116 const s = gs();117 const el = document.getElementById('bs-cnt');118 const pel = document.getElementById('bs-cur');119 if (el && s) el.textContent = '已公开:' + (s.processed || 0) + ' 跳过:' + (s.skipped || 0) + ' 失败:' + (s.failed || 0);120 else if (el) el.textContent = '已公开:0 跳过:0 失败:0';121 if (pel) pel.textContent = '当前页:第 ' + curPg() + ' 页(目标 ' + (s ? s.startPage + '~' + s.endPage : '-') + ')';122 }123 function stUI(t) { const el = document.getElementById('bs-st'); if (el) el.textContent = '状态:' + t; }124
125 function advance() {126 const s = gs();127 if (!s || !s.running || !isLP()) return;128 if (s.done) return;129
130 s.currentPage = curPg();131 ss(s);132 updP();133
134 if (!s.reachedStart) {135 if (curPg() < s.startPage) {136 stUI('跳转到第 ' + s.startPage + ' 页...');137 location.href = LIST_URL + '?page=' + s.startPage;138 return;139 }140 s.reachedStart = true;141 ss(s);142 }143
144 if (curPg() > s.endPage) { finish(); return; }145
146 if (!s.collected) {147 const { queue, skipped } = collect();148 if (queue.length === 0 && document.querySelectorAll('a[href*="/video/BV"]').length === 0) {149 stUI('等待页面加载...');150 setTimeout(() => { if (gs() && gs().running && !gs().done) advance(); }, 2000);151 return;152 }153 s.skipped = (s.skipped || 0) + skipped;154 s.queue = queue;155 s.collected = true;156 ss(s);157 sq(queue);158
159 if (queue.length === 0) {160 stUI('本页无待处理,进入下一页');161 s.collected = false; ss(s); nextPage();162 return;163 }164 goEdit();165 return;166 }167
168 if (s.queue.length > 0) { goEdit(); return; }169 s.collected = false; ss(s); nextPage();170 }171
172 function goEdit() {173 const s = gs();174 if (!s || !s.running) return;175 if (!s.queue || s.queue.length === 0) { advance(); return; }176 const next = s.queue.shift();177 sq(s.queue);178 ss(s);179 stUI('处理 ' + next + ' | 第 ' + s.currentPage + '/' + s.endPage + ' 页');180 location.href = eUrl(next);181 }182
183 function nextPage() {184 const s = gs();185 if (!s || !s.running || s.done) return;186 if (curPg() >= s.endPage) { finish(); return; }187 stUI('进入第 ' + (curPg() + 1) + ' 页...');188 s.collected = false; ss(s);189 location.href = LIST_URL + '?page=' + (curPg() + 1);190 }191
192 function finish() {193 const s = gs(); if (!s) return;194 s.done = true; ss(s);195 alert('🎉 全部完成!\n已公开:' + (s.processed || 0) + ',跳过:' + (s.skipped || 0) + ',失败:' + (s.failed || 0));196 cs(); stUI('全部完成');197 }198
199 async function handleEP() {200 const s = gs();201 if (!s || !s.running || s.done) return;202 updP(); stUI('正在编辑...');203 await slp(2000);204
205 let ok = false, clicked = false;206 const labels = document.querySelectorAll('span.label');207 for (const l of labels) { if (l.textContent.trim().startsWith('更多设置')) { l.click(); clicked = true; break; } }208 if (!clicked) {209 const titles = document.querySelectorAll('div.title');210 for (const t of titles) { if (t.textContent.trim().startsWith('更多设置')) { t.click(); clicked = true; break; } }211 }212 if (!clicked) {213 const all = document.querySelectorAll('span, div, a');214 for (const e of all) { if (e.textContent.trim().startsWith('更多设置')) { e.click(); clicked = true; break; } }215 }216
217 if (clicked) {218 await slp(1200);219 const containers = document.querySelectorAll('.check-radio-v2-container');220 if (containers.length >= 2) {221 const isChecked = containers[0].querySelector('.check-radio-v2-box-checked') !== null;222 if (!isChecked) {223 // 点击"公开可见"(第一个容器)224 const radio = containers[0].querySelector('.check-radio-v2-box, span');225 if (radio) radio.click(); else containers[0].click();226 await slp(800);227 }228 const sub = document.querySelector('span.submit-add');229 if (sub) { sub.click(); ok = true; }230 else {231 const all = document.querySelectorAll('div, button, span');232 for (const e of all) { if (e.textContent.trim() === '立即投稿') { e.click(); ok = true; break; } }233 }234 }235 }236
237 const st = gs();238 if (st) { if (ok) st.processed = (st.processed || 0) + 1; else st.failed = (st.failed || 0) + 1; ss(st); }239 updP();240 stUI(ok ? '已提交,返回列表...' : '失败,返回列表...');241 await slp(2500);242 const st2 = gs();243 const pg = st2 && st2.currentPage ? st2.currentPage : 1;244 location.href = LIST_URL + (pg > 1 ? '?page=' + pg : '');245 }246
247 setTimeout(function () { mkPanel(); updP(); }, 500);248
249 if (isLP()) {250 setTimeout(function () {251 const s = gs();252 if (s && s.running && !s.done) { stUI('自动继续...'); updP(); advance(); updP(); }253 }, 2000);254 }255
256 if (isEP()) { handleEP(); }257})();如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
部分内容可能已过时
分享你的想法,与大家交流讨论