您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
一键取消全部关注,失败自动重试
// ==UserScript== // @name B站全量取关助手 // @namespace https://greasyfork.org/users/1383389 // @version 1.2 // @description 一键取消全部关注,失败自动重试 // @author deepseek // @match https://space.bilibili.com/*/relation/follow // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js // @grant GM_addStyle // @icon https://static.hdslb.com/images/favicon.ico // @license MIT // ==/UserScript== (function() { 'use strict'; class BulkUnfollow { constructor() { this.CSRF = document.cookie.split('; ').find(row => row.startsWith('bili_jct='))?.split('=')[1]; this.UID = window.location.pathname.split('/')[1]; this.DELAY = 150; // 基础延迟 this.RETRY_LIMIT = 3; // 失败重试次数 this.isRunning = false; this.taskQueue = []; this.failedList = []; this.stats = { total: 0, success: 0, failed: 0 }; } // 获取全部关注列表 async fetchAllFollowers() { try { let list = []; let page = 1; while(true) { const { data } = await axios.get( `https://api.bilibili.com/x/relation/followings?vmid=${this.UID}&pn=${page}&ps=100`, { withCredentials: true } ); if (!data.data || !data.data.list || data.data.list.length === 0) break; list = list.concat(data.data.list); if (list.length >= data.data.total) break; page++; } return list; } catch (error) { console.error('获取关注列表失败:', error); return []; } } // 执行取消关注 async executeUnfollow(mid, retryCount = 0) { try { const params = new URLSearchParams(); params.append('fid', mid); params.append('act', 2); params.append('re_src', 11); params.append('csrf', this.CSRF); const { data } = await axios.post( 'https://api.bilibili.com/x/relation/modify', params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, withCredentials: true, timeout: 3000 } ); if (data.code === 0) return true; throw new Error(data.message); } catch (error) { if (retryCount < this.RETRY_LIMIT) { await new Promise(r => setTimeout(r, 500 * (retryCount + 1))); return this.executeUnfollow(mid, retryCount + 1); } return false; } } // 主流程控制 async processAll() { this.isRunning = true; this.stats = { total: 0, success: 0, failed: 0 }; try { // 获取全部关注 const users = await this.fetchAllFollowers(); this.stats.total = users.length; this.updateProgress(); // 执行取消操作 for (const user of users) { if (!this.isRunning) break; const result = await this.executeUnfollow(user.mid); result ? this.stats.success++ : this.stats.failed++; this.updateProgress(); await new Promise(r => setTimeout(r, this.DELAY)); } // 自动重试失败项 if (this.stats.failed > 0) { this.retryFailed(); } else { this.showFinalResult(); } } finally { this.isRunning = false; } } // 失败自动重试 async retryFailed() { let retryCount = 0; while (this.stats.failed > 0 && retryCount < 2) { this.stats.failed = 0; const failedCopy = [...this.failedList]; this.failedList = []; for (const user of failedCopy) { if (!this.isRunning) break; const result = await this.executeUnfollow(user.mid); result ? this.stats.success++ : this.stats.failed++; this.updateProgress(); await new Promise(r => setTimeout(r, this.DELAY)); } retryCount++; } this.showFinalResult(); } // 界面更新 updateProgress() { const progress = document.getElementById('bulk-progress'); if (progress) { progress.innerHTML = ` <div>总进度:${this.stats.success + this.stats.failed}/${this.stats.total}</div> <div>成功:${this.stats.success} | 失败:${this.stats.failed}</div> <div>剩余重试次数:${this.RETRY_LIMIT - this.failedList.length}</div> `; } } // 最终结果显示 showFinalResult() { const result = `操作完成!<br> 成功:${this.stats.success}<br> 失败:${this.stats.failed}<br> ${this.stats.failed > 0 ? '失败项已自动重试' : ''}`; this.showPopup('操作结果', result, true); window.location.reload(); } // 通用弹窗 showPopup(title, content, showClose = true) { const popup = document.createElement('div'); popup.className = 'bulk-popup'; popup.innerHTML = ` <div class="popup-content"> <h3>${title}</h3> <div class="popup-body">${content}</div> ${showClose ? '<button class="popup-close">关闭</button>' : ''} </div> `; document.body.appendChild(popup); popup.querySelector('.popup-close')?.addEventListener('click', () => popup.remove()); } // 创建控制面板 createControlPanel() { const panel = document.createElement('div'); panel.className = 'bulk-control'; panel.innerHTML = ` <div class="control-box"> <button id="start-unfollow">一键取消全部关注</button> <div id="bulk-progress"></div> <button id="stop-unfollow" style="display:none">停止操作</button> </div> `; // 插入到页面合适位置 const container = document.querySelector('#page-follow') || document.body; container.prepend(panel); // 事件绑定 panel.querySelector('#start-unfollow').addEventListener('click', () => { panel.querySelector('#start-unfollow').disabled = true; panel.querySelector('#stop-unfollow').style.display = 'inline-block'; this.processAll(); }); panel.querySelector('#stop-unfollow').addEventListener('click', () => { this.isRunning = false; panel.querySelector('#start-unfollow').disabled = false; panel.querySelector('#stop-unfollow').style.display = 'none'; }); } } // 样式注入 GM_addStyle(` .bulk-control { margin: 20px; padding: 15px; background: #fff; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); } #start-unfollow { padding: 10px 20px; background: #00a1d6; color: white; border: none; border-radius: 5px; cursor: pointer; transition: background 0.3s; } #start-unfollow:hover { background: #0088b3; } #start-unfollow:disabled { background: #cccccc; cursor: not-allowed; } #bulk-progress { margin: 15px 0; padding: 10px; background: #f5f6f7; border-radius: 5px; font-size: 14px; color: #666; } #stop-unfollow { padding: 8px 15px; background: #ff4444; color: white; border: none; border-radius: 5px; cursor: pointer; } .bulk-popup { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; z-index: 999999; } .popup-content { background: white; padding: 20px; border-radius: 10px; min-width: 300px; text-align: center; } .popup-close { margin-top: 15px; padding: 8px 20px; background: #00a1d6; color: white; border: none; border-radius: 5px; cursor: pointer; } `); // 初始化 const unfollow = new BulkUnfollow(); unfollow.createControlPanel(); })();