Greasy Fork

Greasy Fork is available in English.

微博批量删除隐藏助手(适配新版微博)

可指定日期、关键字对微博进行批量删除或设置为仅个人可见,可自动翻页

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         微博批量删除隐藏助手(适配新版微博)
// @namespace    https://github.com/Meteor8
// @version      5.0
// @description  可指定日期、关键字对微博进行批量删除或设置为仅个人可见,可自动翻页
// @author       Meteora
// @match        *.weibo.com/*
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==
 
var intervalTime = 1500;    //操作间隔时间ms
var versionSel = 0; //微博版本选择
var keyWord = "";   //关键字
var endFlag = 0;    //尾页标志
var scrollCnt = 0;  //下滑次数
var failCnt = 0;    //失败次数
var failThreshold = 1;  //失败阈值
var dateFrom, dateTo;
var allFailCnt, allSucCnt;
var notComp = 0;  //是否为快转
allSucCnt = allFailCnt = 0
var episodeSucCnt = 0
dateFrom = "0-0-0";
dateTo = "9999-99-99"
var exeSelect=-1;   //操作类型:-1测试,0删除,1隐藏,2取消快转
 
var itemCntLast = 0;
var itemCntNew = 0;
 
function $(elem) {
    return document.querySelector(elem);
}
function $All(elem) {
    return document.querySelectorAll(elem);
}
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
}
function isDatePart(dateStr) {
    var parts;
    if (dateStr.indexOf("-") > -1) {
        parts = dateStr.split('-');
    } else if (dateStr.indexOf("/") > -1) {
        parts = dateStr.split('/');
    } else {
        return false;
    }
    if (parts.length < 3) {
        return false;
    }
    for (let i = 0; i < 3; i++) {
        if (isNaN(parts[i])) {
            return false;
        }
    }
    let y = parts[0];//年
    let m = parts[1];//月
    let d = parts[2];//日
    if (y > 9999) {
        return false;
    }
    if (m < 1 || m > 12) {
        return false;
    }
    switch (d) {
        case 29:
            if (m == 2) {
                if ((y / 100) * 100 == y && (y / 400) * 400 != y) {
                } else {
                    return false;
                }
            }
            break;
        case 30:
            if (m == 2) {
                return false;
            }
            break;
        case 31:
            if (m == 2 || m == 4 || m == 6 || m == 9 || m == 11) {
                return false;
            }
            break;
        default:
    }
    return true;
}
function dateComp(myDate, setDate){
    var md = new Array();
    var d0 = new Array();
    d0 = setDate.split("-")
    if(myDate[0]=="今" || myDate[myDate.length-1]=="前"){   //今天,10分钟前
        md = (new Date()).toLocaleDateString().split("/")
    }else if(myDate[myDate.length-1]=="日"){    // 1月1日
        md[0] = (new Date()).getFullYear()
        md[1] = myDate.split("月")[0]
        md[2] = myDate.split("月")[1].split("日")[0]
    }else{  //2012-1-15
        md = myDate.split("-")
    }
    for(let i in md) md[i]=parseInt(md[i]);
    for(let i in d0) d0[i]=parseInt(d0[i]);
 
    if(md[0]>d0[0]){
        return 1;
    }else if(md[0]==d0[0]){
        if(md[1]>d0[1]){
            return 1;
        }else if(md[1]==d0[1]){
            if(md[2]>d0[2]){
                return 1;
            }else if(md[2]==d0[2]){
                return 0;
            }
        }
    }
    return -1;
}
 
(function() {
    'use strict';
    window.onload = () => {
        GM_registerMenuCommand('开始运行程序', startBtn);
		/***** =======  Buy-Me-A-Coffee(国内版)  ======= *****/
		const donateWeChatImg = 'https://gitee.com/SolarEclipse/qrcode/raw/master/wx.jpg'; 
		const donateAlipayImg = 'https://gitee.com/SolarEclipse/qrcode/raw/master/ali.jpg'; 
		const afdianLink      = 'https://afdian.com/a/meteora';         // 可选

		// ① 创建右下角“☕ 打赏作者”悬浮按钮
		function createDonateButton () {
			const btn = document.createElement('button');
			btn.textContent = '☕ 打赏作者';
			Object.assign(btn.style, {
				position: 'fixed',
				bottom:  '80px',   // 避开你原本的“开始程序”按钮
				left:   '20px',
				zIndex:  '10000',
				padding: '8px 14px',
				background: '#ffbb00',
				color:  '#000',
				border: 'none',
				borderRadius: '6px',
				cursor: 'pointer',
				boxShadow: '0 2px 8px rgba(0,0,0,.15)'
			});
			btn.onclick = showDonate;
			document.body.appendChild(btn);
		}

		// ② 点击后 / 脚本结束后展示二维码面板
		function showDonate () {
			// 若已存在则先删除,保证只出现一次
			const old = document.getElementById('donate-panel');
			if (old) old.remove();

			const panel = document.createElement('div');
			panel.id = 'donate-panel';
			Object.assign(panel.style, {
				position: 'fixed',
				bottom:  '120px',
				left:   '20px',
				zIndex:  '10001',
				padding: '12px 16px',
				background: '#fff',
				border: '1px solid #ddd',
				borderRadius: '10px',
				boxShadow: '0 4px 12px rgba(0,0,0,.1)',
				textAlign: 'center',
				fontFamily: 'Arial, sans-serif'
			});
			panel.innerHTML = `
				  <div style="display:flex;gap:8px;">
					 <div>
					   <img src="${donateWeChatImg}" referrerpolicy="no-referrer"
							style="width:120px;height:120px;border:1px solid #eee;">
					   <div style="font-size:12px">微信</div>
					 </div>
					 <div>
					   <img src="${donateAlipayImg}" referrerpolicy="no-referrer"
							style="width:120px;height:120px;border:1px solid #eee;">
					   <div style="font-size:12px">支付宝</div>
					 </div>
				  </div>
				<a href="${afdianLink}" target="_blank" style="display:block;margin:6px auto 0;color:#069;text-decoration:none;font-size:13px;">或访问我的爱发电主页 →</a>
				<button id="donate-close" style="margin-top:8px;padding:4px 10px;border:none;border-radius:4px;background:#eee;cursor:pointer;">关闭</button>
			`;
			document.body.appendChild(panel);
			document.getElementById('donate-close').onclick = () => panel.remove();
		}

		// ③ 在脚本加载完就放一个按钮;如果只想“结束时”弹,可以只在 mainLoop 里调用 showDonate()
		createDonateButton();
		// 可选:加入脚本菜单
		GM_registerMenuCommand('☕ 打赏作者', showDonate);
		/***** =======  End Buy-Me-A-Coffee ======= *****/
 
        //扫面页面,滑动到页面最底端
        async function scanPage(){
            var state = false;
            while(!state){
                scrollBy(0, 2000);
                scrollCnt++;
                console.log("*下滑"+scrollCnt)
                await sleep(1000);
                state = $('[node-type="feed_list_page"]') || (scrollCnt>15 && !($('[node-type="lazyload"]')))
            }
            console.log("#到底")
            scrollCnt = 0;
            if(!$('.page.next')){
                endFlag = 1;
                console.log("#尾页");
            }
        }
 
        async function nextPage(){
            $('.page.next').click();
            console.log("*翻页");
            await sleep(5000);
        }
 
        async function exeOp(){
            let allItems = $All('[action-type="feed_list_item"]');
            console.log("#本页共"+allItems.length+"条微博");
            for(let i=0;i<allItems.length;i++){
                let item = allItems[i];
                let content = item.querySelector('[node-type="feed_list_content"]').innerText;
                let wdate = item.querySelector(".S_txt2 > a").getAttribute("title").split(" ")[0]
 
                if(content.indexOf(keyWord)!=-1 && dateComp(wdate,dateFrom)>=0 && dateComp(wdate,dateTo)<=0){
                    item.querySelector('a[action-type="fl_menu"]').click();
                    await sleep(500);
                    if(exeSelect==-1){
                        console.log(wdate);
                        // if(dateComp(wdate,dateFrom)>=0 && dateComp(wdate,dateTo)<=0){
                        //     item.style.color = "blue";
                        // }
                        // item.remove();
                    }else if (exeSelect == 1 && item.getAttribute("action-data") == "cur_visible=0") { // 设为仅个人可见
                        let btntemp = item.querySelector('a[action-type="fl_personalVisible"]') || 
                                      Array.from(item.querySelectorAll('div.woo-box-flex.woo-box-alignCenter.woo-pop-item-main'))
                                          .find(el => el.textContent.includes("转换为自己可见"));
                    
                        if (btntemp) {
                            btntemp.click(); // 点击“设为仅个人可见”
                            await sleep(500);
                    
                            // 点击确认按钮
                            const confirmButton = item.querySelector('a[action-type="ok"]');
                            if (confirmButton) {
                                confirmButton.click();
                                await sleep(intervalTime);
                                console.log("*尝试隐藏" + i);
                            } else {
                                console.error("未找到确认按钮");
                            }
                        } else {
                            console.error("未找到设为仅个人可见的按钮");
                        }
                    }else if(exeSelect==0){ //删除微博
                        const delBtn = item.querySelector('a[action-type="feed_list_delete"]');
                        if(delBtn != null){
                            delBtn.click();
                            await sleep(500);
                            item.querySelector('a[action-type="ok"]').click();
                            await sleep(intervalTime);
                            console.log("*尝试删除"+i);
                        }else{
                            notComp = 1;
                        }
                    }else if(exeSelect==2){ //取消快转
                        const unFastBtn = item.querySelector('a[action-type="feed_list_delete_fast_reported"]');
                        if (unFastBtn != null){
                            unFastBtn.click();
                            await sleep(intervalTime);
                            console.log("*尝试取消快转"+i);
                        }else{
                            notComp = 1;
                        }
                    }
 
                    // 操作失败,否则成功
                    if($('[action-type="ok"]')){
                        if($('[node-type="text"]').innerText.indexOf("繁忙")!=-1 && failCnt<=failThreshold){
                            failCnt++;
                            console.log("#系统繁忙,3s后进行第"+(failCnt+1)+"次尝试"+i);
                            i--;
                            await sleep(3000);
                        }else{
                            failCnt = 0
                            allFailCnt++;
                            console.log("#操作失败"+i)  //打印失败原因
                        }
                        $('[action-type="ok"]').click();
                    }else{
                        if(notComp == 1){
                            notComp = 0;
                        }else{
                            allSucCnt++;
                            episodeSucCnt++;
                            console.log("#操作成功"+i);
                        }
                    }
                }
            }
        }
 
        async function mainLoop(){
            while(1){
                await scanPage();
                await exeOp();
                // await sleep(1000*15);
                if(endFlag) break;
                await nextPage();
            }
            alert("操作执行完毕\n共匹配符合条件微博:"+(allSucCnt+allFailCnt)+"条\n其中,操作成功"+allSucCnt+"条,失败"+allFailCnt+"条")
            console.log("#结束")
        }
 
        async function scrollPage(){
            while(scrollCnt < 2){
                scrollBy(0, 2000);
                scrollCnt++;
                console.log("*下滑"+scrollCnt)
                await sleep(1000);
            }
            scrollCnt = 0;
        }
 
        async function exeOpNew(item,i){
            let content = item.querySelector(".detail_wbtext_4CRf9").innerText;
            let wdate = item.querySelector(".head-info_time_6sFQg").getAttribute("title").split(" ")[0]
 
            if(content.indexOf(keyWord)!=-1 && dateComp(wdate,dateFrom)>=0 && dateComp(wdate,dateTo)<=0){
                // item.querySelector('.woo-pop-ctrl > div >i').click();
                // await sleep(500);
                if(exeSelect==-1){
                    console.log(wdate);
                    if(dateComp(wdate,dateFrom)>=0 && dateComp(wdate,dateTo)<=0){
                        item.style.color = "blue";
                    }
                    // item.remove();
                    await sleep(intervalTime);
                }else if (exeSelect == 1 && item.querySelector('.title_wrap_3e__u') == null && item.querySelector('.head_fastbehind_1StRl') == null) { // 设为仅个人可见
                    const ctrlButton = item.querySelector('.woo-pop-ctrl > div > i');
                    if (ctrlButton) {
                        ctrlButton.click(); // 点击弹出菜单
                        await sleep(800);
                
                        // 尝试找到“转换为自己可见”按钮
                        const options = Array.from(item.querySelectorAll('div.woo-pop-wrap-main > div')).slice(-4); // 检索最后几个菜单项
                        const targetButton = options.find(option => option.innerText.trim() === '转换为自己可见');
                
                        if (targetButton) {
                            targetButton.click(); // 点击“转换为自己可见”
                            console.log(`*成功找到并点击隐藏按钮 ${i}`);
                        } else {
                            console.log(`*未找到隐藏按钮 ${i}`);
                        }
                    } else {
                        console.log(`*未找到弹出菜单按钮 ${i}`);
                    }
                
                    await sleep(intervalTime);
                }
                else if (exeSelect == 0 && item.querySelector('.head_fastbehind_1StRl') == null) { // 删除微博
                    const ctrlButton = item.querySelector('.woo-pop-ctrl > div > i');
                    if (ctrlButton) {
                        ctrlButton.click(); // 点击弹出菜单
                        await sleep(800);
                
                        // 动态查找“删除”按钮
                        const options = Array.from(item.querySelectorAll('div.woo-pop-wrap-main > div')).slice(-3); // 检索最后三个菜单项
                        const delBtn = options.find(option => option.innerText.trim() === '删除');
                
                        if (delBtn) {
                            delBtn.click(); // 点击“删除”按钮
                            await sleep(500);
                
                            // 点击确认删除的按钮
                            const confirmButton = document.querySelectorAll(".woo-button-round.woo-dialog-btn")[1];
                            if (confirmButton) {
                                confirmButton.click();
                                await sleep(intervalTime);
                                console.log(`*尝试删除微博 ${i}`);
                            } else {
                                console.error(`*未找到确认删除按钮 ${i}`);
                            }
                        } else {
                            console.log(`*未找到删除按钮 ${i}`);
                            notComp = 1;
                        }
                    } else {
                        console.log(`*未找到弹出菜单按钮 ${i}`);
                        notComp = 1;
                    }
                }                
                else if (exeSelect == 2 && item.querySelector('.head_fastbehind_1StRl') != null) { // 取消快转
                    const ctrlButton = item.querySelector('.woo-pop-ctrl > div > i');
                    if (ctrlButton) {
                        ctrlButton.click(); // 点击弹出菜单
                        await sleep(800);
                
                        // 动态查找“取消快转”按钮
                        const options = Array.from(item.querySelectorAll('div.woo-pop-wrap-main > div')).slice(-3); // 检索最后三个菜单项
                        const unFastBtn = options.find(option => option.innerText.trim() === '取消快转');
                
                        if (unFastBtn) {
                            unFastBtn.click(); // 点击“取消快转”按钮
                            await sleep(500);
                
                            // 点击确认按钮
                            const confirmButton = document.querySelectorAll(".woo-button-round.woo-dialog-btn")[1];
                            if (confirmButton) {
                                confirmButton.click();
                                await sleep(intervalTime);
                                console.log(`*尝试取消快转 ${i}`);
                            } else {
                                console.error(`*未找到确认取消快转按钮 ${i}`);
                            }
                        } else {
                            console.error(`*未找到取消快转按钮 ${i}`);
                            notComp = 1;
                        }
                    } else {
                        console.error(`*未找到弹出菜单按钮 ${i}`);
                        notComp = 1;
                    }
                }
                else if (exeSelect == 3 && item.querySelector('.title_wrap_3e__u') == null && item.querySelector('.head_fastbehind_1StRl') == null) { // 设为仅粉丝可见
                    const ctrlButton = item.querySelector('.woo-pop-ctrl > div > i');
                    if (ctrlButton) {
                        ctrlButton.click(); // 点击弹出菜单
                        await sleep(800);
                
                        // 尝试找到“转换为自己可见”按钮
                        const options = Array.from(item.querySelectorAll('div.woo-pop-wrap-main > div')).slice(-4); // 检索最后几个菜单项
                        const targetButton = options.find(option => option.innerText.trim() === '转换为粉丝可见');
                
                        if (targetButton) {
                            targetButton.click(); // 点击“转换为粉丝可见”
                            console.log(`*成功找到并点击隐藏按钮 ${i}`);
                        } else {
                            console.log(`*未找到隐藏按钮 ${i}`);
                        }
                    } else {
                        console.log(`*未找到弹出菜单按钮 ${i}`);
                    }
                
                    await sleep(intervalTime);
                }
                else if (exeSelect == 4 && item.querySelector('.title_wrap_3e__u') == null && item.querySelector('.head_fastbehind_1StRl') == null) { // 设为仅好友圈可见
                    const ctrlButton = item.querySelector('.woo-pop-ctrl > div > i');
                    if (ctrlButton) {
                        ctrlButton.click(); // 点击弹出菜单
                        await sleep(800);
                
                        // 尝试找到“转换为自己可见”按钮
                        const options = Array.from(item.querySelectorAll('div.woo-pop-wrap-main > div')).slice(-4); // 检索最后几个菜单项
                        const targetButton = options.find(option => option.innerText.trim() === '转换为好友圈可见');
                
                        if (targetButton) {
                            targetButton.click(); // 点击“转换为好友圈可见”
                            console.log(`*成功找到并点击隐藏按钮 ${i}`);
                        } else {
                            console.log(`*未找到隐藏按钮 ${i}`);
                        }
                    } else {
                        console.log(`*未找到弹出菜单按钮 ${i}`);
                    }
                
                    await sleep(intervalTime);
                }
                else{
                    allSucCnt--;
                    episodeSucCnt--;
                }
 
                // 操作失败,否则成功
                if($('[action-type="ok"]')){
                    if($('[node-type="text"]').innerText.indexOf("繁忙")!=-1 && failCnt<=failThreshold){
                        failCnt++;
                        console.log("#系统繁忙,3s后进行第"+(failCnt+1)+"次尝试"+i);
                        i--;
                        await sleep(3000);
                    }else{
                        failCnt = 0
                        allFailCnt++;
                        console.log("#操作失败"+i)  //打印失败原因
                    }
                    $('[action-type="ok"]').click();
                }else{
                    if(notComp == 1){
                        notComp = 0;
                    }else{
                        allSucCnt++;
                        episodeSucCnt++;
                        console.log("#操作成功"+i);
                    }
                }
            }
        }
 
 
 
        async function mainLoopNew(){
            await sleep(1500);
 
            while(!endFlag){
                episodeSucCnt = 0;
                // 获取微博
                let allItems = $All('.vue-recycle-scroller__item-view');
 
                for(let i=0; i<allItems.length; i++){
                    await exeOpNew(allItems[i],i);
                }
 
                // 判断结尾
                if($('.Bottom_text_1kFLe')!=null){
                    endFlag = 1;
                    console.log("#尾页");
                }
 
                // 没有可操作的任务再下滑
                if(episodeSucCnt==0){
                    await scrollPage();
                }
            }
 
            alert("操作执行完毕\n共匹配符合条件微博:"+(allSucCnt+allFailCnt)+"条\n其中,操作成功"+allSucCnt+"条,失败"+allFailCnt+"条")
            console.log("#结束")
			showDonate();   // ← 新增这一行
        }
 
        function setUp(){
            exeSelect = -1;
            keyWord;
            dateFrom = "2018-11-15";
            dateTo = "2018-11-15";
            while(1){
                versionSel = prompt("请输入当前微博类型(输入数字)\n【0】旧版微博(已弃用!)\n【1】新版微博")
                if(versionSel=="0" || versionSel=="1" ) break;
                alert("请按提示操作")
            }
            while(1){
                exeSelect = prompt("请输入操作类型(输入数字)\n【0】删除微博(不可恢复,谨慎操作!)\n【1】隐藏微博(设为仅个人可见,推荐)\n【2】取消快转\n【3】仅粉丝可见\n【4】仅好友圈可见")
                if(exeSelect=="0" || exeSelect=="1" || exeSelect=="2" || exeSelect=="3" || exeSelect=="4"|| exeSelect=="-1") break;
                alert("请按提示操作")
            }
            keyWord = prompt("请输入要操作微博的关键字。\n【默认不填为全匹配】\n(功能弃用!建议使用微博自带搜索)");
            while(1){
                dateFrom = prompt("请输入要操作微博的发布日期时间段的【开始日期】(包括当日)。\n【请按格式填写,例:2021-2-29】\n【默认不填为全匹配】\n(功能弃用!建议使用微博自带搜索)");
                if (dateFrom == "") dateFrom = "0000-1-1";
                dateTo = prompt("请输入要操作微博的发布日期时间段的【截至日期】(包括当日)。(建议使用微博自带搜索)\n【请按格式填写,例:2021-2-29】\n【默认不填为全匹配】\n(功能弃用!建议使用微博自带搜索)")
                if (dateTo == "") dateTo = "9999-12-31";
                if(isDatePart(dateFrom) && isDatePart(dateTo) && dateComp(dateFrom,dateTo)<=0) break;
                alert("错误,请重新输入:\n1.请检查开始日期是否小于或等于截止日期\n2.请检查日期格式是否正确")
            }
            // inTim = prompt("设置两次操作间隙时间(单位:秒)\n【间隔过短容易被服务器检测异常,推荐1.5秒】【不填默认为1.5秒】")
        }
        // 创建一个按钮元素
        var button = document.createElement("button");
        button.innerHTML = "🚀 开始程序";
        button.style.position = "fixed";
        button.style.bottom = "20px"; // 距离底部的距离
        button.style.left = "20px"; // 距离左侧的距离
        button.style.zIndex = "9999"; // 确保按钮在最顶层
 
        button.style.padding = "10px 20px";
        button.style.backgroundColor = "#3498db";
        button.style.color = "#fff";
        button.style.border = "none";
        button.style.borderRadius = "5px";
        button.style.fontFamily = "Arial, sans-serif";
        button.style.fontSize = "14px";
        button.style.cursor = "pointer";
        button.style.boxShadow = "0 4px 6px rgba(0, 0, 0, 0.1)";
 
 
 
        // 将按钮添加到页面中
        document.body.appendChild(button);
 
        function startBtn(){
            //开始
            var w = confirm("欢迎使用微博删除助手,单击“确认”开始配置删除设置,单击“取消”退出");
            if (w === true) {
                setUp();
                var exeStr = "";
                var verStr = "";
                if(exeSelect=="0"){
                    exeStr = "删除微博"
                }else if(exeSelect=="1"){
                    exeStr = "隐藏微博"
                }else if(exeSelect=="2"){
                    exeStr = "取消快转"
                }else if(exeSelect=="3"){
                    exeStr = "仅粉丝可见"
                }else if(exeSelect=="4"){
                    exeStr = "仅好友圈可见"
                }else{
                    exeStr = "测试"
                }
                if (versionSel=="0"){
                    verStr = "旧版微博";
                }else{
                    verStr = "新版微博";
                }
                var c = confirm("配置完毕。\n【微博版本】:"+verStr+"\n【操作类型】:"+exeStr+"\n【微博内容包括】:"+keyWord+"\n【微博发布日期】:从 "+dateFrom+"(包括) 至 "+dateTo+"(包括) \n单击”确认“开始")
                if(c===true){
                    if (versionSel=="0"){
                        mainLoop();
                    }else{
                        mainLoopNew();
                    }
                }
            }
        }
 
        // 为按钮添加点击事件监听器
        button.addEventListener("click", startBtn);
    };
})();