前言
赛博僵尸道长是针对微博兴趣推荐用户以及不活跃用户问题(俗称僵尸粉)而设计的,旨在轻松快捷地清除微博用户的僵尸粉,使得用户发出的微博获得更多有效曝光及互动。
更新公告
2022-07-07:
1.添加不相关用户清除功能
2.修复互相关注失效bug
2022-07-02:
1.修复内存泄漏问题。
2.添加可交互面板。
2022-06-29
1.修复深度清粉时页面异常的情况,并加快清理效率。
2.增加心跳复活功能。
2022-06-26:
提供 快速清粉 和 深度清粉 两个模式。
快速清粉:可选择清理满足以下条件的粉丝。
①兴趣推荐
②微博数<3且粉丝数<2 (可以修改参数和判断逻辑,详见说明)
③默认头像
深度清粉:在快速清粉的基础上,可以扫描并清理一定时间内没发微博或点赞的粉丝。(默认365天内,可修改参数)
注意:深度清粉会访问粉丝页面检查微博和点赞,效率较低。深度清粉模式运行时会访问每个粉丝的页面查看微博跟点赞,这是正常现象,不必恐慌。
使用说明
代码仅适用于旧版微博,新版微博用户请切换回旧版微博。
复制后,电脑页面打开至粉丝页面的第一页,右键菜单->检查元素打开开发者工具,黏贴到console窗口后按Enter键运行代码。
运行代码后,关掉开发者工具,否则可能再清粉过程中引起网页崩溃,网页将变成如下图所示:
快速清粉参数:
①清除兴趣推荐用户:清理通过兴趣推荐关注过来的用户。
②检查相互关注:如果是相互关注的用户则跳过。
③检查粉丝来源:开启后只检查通过兴趣推荐或者微博推荐关注过来的粉丝。
④清除不活跃用户:开启后将检查粉丝数和微博数低于指定数量用户。
⑤最低粉丝数 和 最低微博数:用于判断用户活跃度。
⑥满足任一条件即清除:只要 粉丝数 或 微博数 小于给定的数值,即判断为不活跃用户。
⑦清除默认头像用户:清理头像是默认头像的用户。
深度清粉参数:
①开启深度清粉:勾选后开启深度清粉模式,运行时会访问每个粉丝的页面查看微博跟点赞,一旦在指定时间内没有发过微博或点赞,则视为不活跃用户。
②无视用户最近点赞:开启后深度模式将不去检查用户点赞。
③最小不活跃天数:用于判断用户是否不活跃。
④开启检查关注:勾选后会在深度清粉时去检查当前用户的共同关注
⑤最小共同关注用户数:用于判断当前用户是否属于同一关系圈。
⑥无视蓝V用户:开启后检查共同关注时跳过官方认证用户,企业号的僵尸最多,默认开启。
⑦无视黄V用户:开启后检查共同关注时跳过个人认证用户,个人认证号僵尸也比较多,可酌情开启。
检测按钮:从当前页开始检测僵尸粉。(不做清理)
清粉按钮:从当前页开始检测并清理僵尸粉。
重要事情说三遍:
粉丝页面里选择 排序->我未关注 后使用代码清理
粉丝页面里选择 排序->我未关注 后使用代码清理
粉丝页面里选择 排序->我未关注 后使用代码清理
如删粉力度不够,除了调高 最小粉丝数 和 最小微博数 之外,还可将开关满足任一条件即清除打开,条件将变为只要 粉丝数 或 微博数 小于给定的数值,即判断为不活跃用户。
进阶用法
① 名字为【用户xxxxxx】基本都是僵尸粉,针对此类用户,可以在搜索栏里搜索关键字“用户”,然后最小微博数跟最小粉丝数调高并打开开关满足任一条件即清除,加大力度清理。
使用前请仔细阅读说明。
使用前请仔细阅读说明。
使用前请仔细阅读说明。
代码
let removeTargetFans =false;/*是否删除符合条件的粉丝,默认关闭*/let deepSearchMode =false;/*是否开启深度清理模式*/let ignoreLikes =true;/*是否无视用户最近点赞*/let minDayCount =180;/*最小不活跃天数*/let checkConnection =false;/*是否检查微关系*/let ignoreBlueV =true;/*无视蓝V用户*/let ignoreYellowV =false;/*无视黄V用户*/let minSameFollowedCount =3;/*最小共同关注用户数*/let fansMinCount =2;/*最小粉丝数*/let weiboMinCount =3;/*最小微博数*/let totalCount =0;let checkIsFromRecommended =true;/*是否检查通过推荐关注*/let checkIsInactive =true;/*是否检查不活跃用户*/let checkFansOrWeibo =false;/*是否只判断粉丝数或微博数*/let checkIsFollowing =true;/*是否检查相互关注*/let checkIsDefaultIcon =false;/*是否检查默认头像*/let checkIsNormalFollowed =false;/*是否检查关注来源*/let isError =false;let isRunning =false;functionclearLog(){let logger = document.querySelector("p.logger");
logger.innerHTML ="";}functionlogError(msg){let logger = document.querySelector("p.logger");let parent = logger.parentElement;
logger.innerHTML +="<span style='color: darkred; font-weight:bold;'>"+ msg +"</span><br>";
parent.scrollTop = parent.scrollHeight;}functionlogSuccessMsg(msg){let logger = document.querySelector("p.logger");let parent = logger.parentElement;
logger.innerHTML +="<span style='color: forestgreen;'>"+ msg +"</span><br>";
parent.scrollTop = parent.scrollHeight;}functionlogImportantMsg(msg){let logger = document.querySelector("p.logger");let parent = logger.parentElement;
logger.innerHTML +="<pre style='font-weight:bold'>"+ msg +"</pre>";
parent.scrollTop = parent.scrollHeight;}functionlogMsg(msg){let logger = document.querySelector("p.logger");let parent = logger.parentElement;
logger.innerHTML +="<pre style='tab-size: 15em;'>"+ msg +"</pre>";
parent.scrollTop = parent.scrollHeight;}functioncheckRunning(iframe, addr){if(!isRunning){if(iframe !=null){
iframe.onload=()=>{ iframe.contentDocument.body.querySelector("div[node-type=outer]")?.remove();};
iframe.contentWindow.location.assign(addr);
iframe.src = addr;}if(removeTargetFans)logImportantMsg("总共删除了 "+ totalCount +" 个疑似僵尸粉");elselogImportantMsg("总共发现了 "+ totalCount +" 个疑似僵尸粉");}return isRunning;}asyncfunctionremoveFanMainFunc(startIndex){constdelay=ms=>newPromise(res=>setTimeout(res, ms));const minute =1000*60;const hour = minute *60;const day = hour *24;clearTimeout();
isError =false;if(!checkRunning(null,""))return;let iframe = document.querySelector("iframe");let currPageAddr = iframe.src;let next = iframe.contentDocument.querySelector(".page.next.S_txt1.S_line1");if(next ==null){awaitnewPromise((resolve)=>{if(iframe.contentWindow.location.href === currPageAddr){
iframe.contentWindow.location.reload();}else{
iframe.contentWindow.location.assign(currPageAddr);}
iframe.onload=()=>{resolve();}});awaitdelay(500);
next = iframe.contentDocument.querySelector(".page.next.S_txt1.S_line1");if(next ==null){
isError =true;if(removeTargetFans)logError("页面异常,退出程序。总计清理了 "+ totalCount +" 个疑似僵尸粉");elselogError("页面异常,退出程序。总计发现了 "+ totalCount +" 个疑似僵尸粉");return;}}let currPageNum = iframe.contentDocument.querySelector(".page.S_txt1.S_bg1").innerText;let nextPageAddr = next.href;let fans = iframe.contentDocument.querySelectorAll("li.follow_item.S_line2");let fanInfos =[];let count =0;for(let i = startIndex; i < fans.length; i++){let isFromRecommended =false;let isInactive =false;let isFollowing =false;let isDefaultIcon =false;let isNormalFollowed =false;let fansCount, weiboCount;let link2s = fans[i].querySelector("div.info_from")?.querySelector("a");
isNormalFollowed = link2s !=null&& link2s.innerText !=="兴趣推荐"&& link2s.innerText !=="微博推荐";/*是否为非推荐的会员*/if(isNormalFollowed && fans[i].querySelector("a[title=微博会员]")!=null)continue;/*关注来源*/if(checkIsFromRecommended){
isFromRecommended = link2s !=null&& link2s.innerText ==="兴趣推荐";}let userData = fans[i].getAttribute('action-data');let userInfos = userData.split('&');let userID = userInfos[0].slice(4);let userName = userInfos[1].slice(6);/*粉丝数与微博数*/if(checkIsInactive){let infos = fans[i].querySelectorAll("span.conn_type.W_vline.S_line1");if(infos.length >=2){
fansCount = infos[0].querySelector("a[target=_blank]").innerText;if(fansCount[fansCount.length -1]==='万') fansCount = fansCount.slice(0, fansCount.length -1)*10000;elseif(fansCount[fansCount.length -1]==='亿') fansCount = fansCount.slice(0, fansCount.length -1)*100000000;
weiboCount = infos[1].querySelector("a[target=_blank]").innerText;if(weiboCount[fansCount.length -1]==='万') weiboCount = weiboCount.slice(0, weiboCount.length -1)*10000;elseif(weiboCount[fansCount.length -1]==='亿') weiboCount = weiboCount.slice(0, weiboCount.length -1)*100000000;
fansCount =parseInt(fansCount);
weiboCount =parseInt(weiboCount);if(checkFansOrWeibo)
isInactive = fansCount < fansMinCount || weiboCount < weiboMinCount;else
isInactive = fansCount < fansMinCount && weiboCount < weiboMinCount || weiboCount ===0|| fansCount ===0;}}/*是否为默认头像*/if(checkIsDefaultIcon){let icon = fans[i].querySelector("img");
isDefaultIcon = icon !=null&& icon.src.includes("/default/images/default_avatar_");}/*是否互相关注*/if(checkIsFollowing){
isFollowing = fans[i].querySelector("a.W_btn_b").innerText !=null&& fans[i].querySelector("a.W_btn_b").innerText.includes("互相关注");}let fanMainPageAddr = fans[i].querySelector('a.S_txt1').href +"&is_all=1";
fanInfos.push({userID, userName, fansCount, weiboCount, fanMainPageAddr, isInactive,isFromRecommanded: isFromRecommended, isNormalFollowed, isDefaultIcon, isFollowing})}for(let i =0; i < fanInfos.length; i++){if(!checkRunning(iframe, currPageAddr))return;let info = fanInfos[i];let isZombie =false;if(!info.isFollowing &&(info.isDefaultIcon ||!(checkIsNormalFollowed && info.isNormalFollowed)))if(info.isFromRecommanded || info.isInactive || info.isDefaultIcon)
isZombie =true;if(deepSearchMode &&!isZombie &&!info.isFollowing){awaitnewPromise((resolve)=>{iframe.contentWindow.location.assign(info.fanMainPageAddr); iframe.onload=()=>{ iframe.contentDocument?.body.querySelector("div[node-type=outer]")?.remove();resolve();}});awaitdelay(500);let weibos = iframe.contentDocument.querySelectorAll("div.WB_cardwrap.WB_feed_type.S_bg2.WB_feed_like");if(weibos.length ===0){if(info.weiboCount >0){awaitnewPromise((resolve)=>{iframe.contentWindow.location.reload(); iframe.onload=()=>{ iframe.contentDocument?.body.querySelector("div[node-type=outer]")?.remove();resolve();}});awaitdelay(500);}
weibos = iframe.contentDocument.querySelectorAll("div.WB_cardwrap.WB_feed_type.S_bg2.WB_feed_like");}if(weibos.length >0){let invalidWeiboCount =0;let validWeiboCount =0;for(let weiboIndex =0; weiboIndex < weibos.length; weiboIndex++){if(ignoreLikes && weibos[weiboIndex].querySelector("div.WB_cardtitle_b.S_line2")!=null)continue;let weiboInfos = weibos[weiboIndex].querySelector("div.WB_from.S_txt2").querySelectorAll("a.S_txt2");if(weiboInfos.length >=2){let weiboSrc = weiboInfos[1].innerText;if(weiboSrc !=null&&(weiboSrc.includes("生日动态")|| weiboSrc.includes("渔场")||
weiboSrc.includes("活动")|| weiboSrc.includes("森林")|| weiboSrc.includes("微博积分")||
weiboSrc.includes("支付宝")|| weiboSrc.includes("淘宝")|| weiboSrc.includes("芭芭农场")||
weiboSrc.includes("任务")|| weiboSrc.includes("签到")|| weiboSrc.includes("新浪游戏")||
weiboSrc.includes("微博游戏")|| weiboSrc.includes("红包")|| weiboSrc.includes("微博会员")||
weiboSrc.includes("微博运动")|| weiboSrc.includes("熊猫守护者")|| weiboSrc.includes("点淘"))){
invalidWeiboCount++;continue;}}if(Math.round((Math.round(newDate().getTime())- weiboInfos[0].getAttribute("date"))/day)<= minDayCount){
validWeiboCount++;}}if(invalidWeiboCount >3){
info.isIrrelevant =true;
isZombie =true;}if(validWeiboCount <3){
info.isInactive =true;
isZombie =true;}}else{if(iframe.contentDocument.querySelector('div.WB_cardwrap.WB_empty_height.S_bg2')!=null){
info.isInactive =true;
isZombie =true;}}if(!isZombie && checkConnection){let connection = iframe.contentDocument.querySelector("div.PCD_user_a.PCD_user_a1")?.querySelector("div.WB_innerwrap");if(connection !=null){let connInfos = connection.querySelectorAll("h2.main_title.W_fb.W_f14");if(connInfos.length >0){let fan_following = connInfos[0].querySelector("a");let needSearch =true;if(!fan_following.innerHTML.includes("共同关注")){
info.isIrrelevant =true;
isZombie =true;}if(connInfos.length >=2){let fan_fans = connInfos[1].querySelector("a");if(fan_fans.innerHTML.includes("我关注的人也")){
info.isInactive =false;
needSearch =false;}}let minCount = minSameFollowedCount;if(!info.isNormalFollowed) minCount +=5;if(needSearch &&!isZombie){let followingPageAddr = fan_following.href;let validCount =0;for(validCount =0;validCount < minCount && followingPageAddr !=="";){if(!checkRunning(iframe, currPageAddr))return;awaitnewPromise((resolve)=>{iframe.contentWindow.location.assign(followingPageAddr); iframe.onload=()=>{iframe.contentDocument?.body.querySelector("div[node-type=outer]")?.remove();resolve();}});awaitdelay(500);let followings = iframe.contentDocument.body.querySelectorAll("li.follow_item.S_line2");for(let fIndex =0; fIndex < followings.length; fIndex++){let currFollowing = followings[fIndex];if(ignoreBlueV &&(currFollowing.querySelector("i.W_icon.icon_approve_co")!=null|| currFollowing.querySelector("i.W_icon_co1.icon_approve_co")!=null))continue;if(ignoreYellowV &&(currFollowing.querySelector("i.W_icon.icon_approve_gold")!=null|| currFollowing.querySelector("i.W_icon.icon_approve")!=null))continue;
validCount++;}
followingPageAddr ="";let nextFollowingBtn = iframe.contentDocument?.body.querySelector("a.page.next.S_txt1.S_line1");if(nextFollowingBtn !=null)
followingPageAddr = nextFollowingBtn.href;}if(validCount < minCount){
info.isIrrelevant =true;
isZombie =true;}}}else{
info.isIrrelevant =true;
isZombie =true;}}}}if(isZombie){let reason ="原因: ";if(info.isFromRecommanded)
reason +=" 兴趣推荐";if(info.isInactive)
reason +=" 不活跃用户";if(info.isIrrelevant)
reason +=" 不相关用户";if(info.isDefaultIcon)
reason +=" 默认头像";if(removeTargetFans){let fData =newFormData();
fData.append("uid", info.userID);
fData.append("_t","0");const json =awaitfetch('/aj/f/remove?ajwvr=6&__rnd='+ Math.round(newDate().getTime()),{method:"POST",body: fData
}).then(response=> response.json()).catch((e)=>{});if(json.code ==100000){logSuccessMsg(info.userName +"\t删除成功 "+ reason);
count++;
totalCount++;}elselogError(info.userName +"\t删除失败 ");}else{logMsg(info.userName +"\t疑似僵尸粉 "+ reason);
count++;
totalCount++;}}}if(!checkRunning(iframe, currPageAddr))return;if(currPageNum <=250&& nextPageAddr !==""){
startIndex =0;let nextAddr = nextPageAddr;if(removeTargetFans){logImportantMsg("第 "+ currPageNum +" 页删除了 "+ count +" 个粉丝");if(count >0){
startIndex = fans.length - count;if(startIndex <0) startIndex =0;
nextAddr = currPageAddr;}}else{logImportantMsg("第 "+ currPageNum +" 页发现了 "+ count +" 个疑似僵尸粉");}
iframe.onload=()=>{setTimeout(()=>RemoveFans(startIndex),1000); iframe.onload =null; iframe.contentDocument.body.querySelector("div[node-type=outer]")?.remove();};if(iframe.contentWindow.location.href === nextAddr){
iframe.contentWindow.location.reload();
iframe.src = nextAddr;}else{
iframe.contentWindow.location.assign(nextAddr);
iframe.src = nextAddr;}}else{clearInterval();SetMode("ready");if(removeTargetFans)logImportantMsg("总共删除了 "+ totalCount +" 个疑似僵尸粉");elselogImportantMsg("总共发现了 "+ totalCount +" 个疑似僵尸粉");
iframe.onload=()=>{ iframe.contentDocument.body.querySelector("div[node-type=outer]")?.remove();};
iframe.contentWindow.location.assign(currPageAddr);
iframe.src = currPageAddr;}}functionRecoverRemoveFansFunc(){if(isError){let p =newPromise(function(){removeFanMainFunc(0)});}}functionRemoveFans(startIndex){let p =newPromise(function(){removeFanMainFunc(startIndex)});}letInitParameters=()=>{
checkIsFromRecommended = document.body.querySelector("input#checkIsFromRecommended").checked;
checkIsFollowing = document.body.querySelector("input#checkIsFollowing").checked;
checkIsNormalFollowed = document.body.querySelector("input#checkIsNormalFollowed").checked;
checkIsDefaultIcon= document.body.querySelector("input#checkIsDefaultIcon").checked;
checkIsInactive = document.body.querySelector("input#checkIsInactive").checked;
checkFansOrWeibo = document.body.querySelector("input#checkFansOrWeibo").checked;
fansMinCount =parseInt(document.body.querySelector("input#fansMinCount").value);
weiboMinCount =parseInt(document.body.querySelector("input#weiboMinCount").value);
deepSearchMode = document.body.querySelector("input#deepSearchMode").checked;
ignoreLikes = document.body.querySelector("input#ignoreLikes").checked;
minDayCount =parseInt(document.body.querySelector("input#minDayCount").value);
checkConnection = document.body.querySelector("input#checkConnection").checked;
ignoreBlueV = document.body.querySelector("input#ignoreBlueV").checked;
ignoreYellowV = document.body.querySelector("input#ignoreYellowV").checked;
minSameFollowedCount =parseInt(document.body.querySelector("input#minSameFollowedCount").value);};letStartCheckFans=()=>{SetMode("running");InitParameters();clearLog();
totalCount =0;
removeTargetFans =false;
isRunning =true;setInterval(RecoverRemoveFansFunc,15000);RemoveFans(0);};letStartRemoveFans=()=>{SetMode("running");InitParameters();clearLog();
totalCount =0;
removeTargetFans =true;
isRunning =true;setInterval(RecoverRemoveFansFunc,15000);RemoveFans(0);};letStopFunc=()=>{SetMode("ready");clearInterval();clearTimeout();
isRunning =false;};letSetDeepSearchParam=()=>{let disable = document.body.querySelector("input#deepSearchMode").checked ===false;let params = document.body.querySelectorAll("input.DeepSearchParam");for(let i =0; i < params.length; i++)
params[i].disabled = disable;};letSetMode=(mode)=>{let params = document.querySelector("div.parameter").querySelectorAll("input");let readyPanel = document.querySelector("div.ready");let runningPanel = document.querySelector("div.running");if(mode ==="running"){for(let i =0; i < params.length; i++) params[i].disabled =true;
readyPanel.style.display ="none";
runningPanel.style.display ="";}elseif(mode ==="ready"){for(let i =0; i < params.length; i++) params[i].disabled =false;
runningPanel.style.display ="none";
readyPanel.style.display ="";}};letReplaceHTML=()=>{
document.head.innerHTML ='<meta charset="UTF-8"><title>赛博僵尸道长</title>';let body ='<div class="left" style="position: fixed; display: flex; flex-direction: column;top:0; left:0; bottom:0; width:500px; background-color: burlywood;"><h1 style="text-align:center; margin: 10px;"> 赛博僵尸道长<span style="font-size: 20px;">v1.2</span></h1><div class="parameter"><h3>快速清粉参数</h3><table style="width: 100%; font-size: 15px;" ><tr><td><input id="checkIsFromRecommended" type="checkbox" style="height: 15px; width: 15px;" checked>清除兴趣推荐用户</td><td><input id="checkIsFollowing" type="checkbox" style="height: 15px; width: 15px;" checked>检查相互关注</td><td><input id="checkIsNormalFollowed" type="checkbox" style="height: 15px; width: 15px;">检查粉丝来源</td></tr><tr style="height: 10px;"></tr><tr><td rowspan="2"><input id="checkIsInactive" type="checkbox" style="height: 15px; width: 15px;" checked>清除不活跃用户</td><td> 最低粉丝数<input id="fansMinCount" type="number" style="height: 15px; width: 60px;" min="0" value="2" ></td><td rowspan="2"><input id="checkFansOrWeibo" type="checkbox" style="height: 15px; width: 15px;" >满足任一条件即清除</td></tr><tr><td> 最低微博数<input id="weiboMinCount" type="number" style="height: 15px; width: 60px;" min="0" value="3" ></td></tr><tr><td><input id="checkIsDefaultIcon" type="checkbox" style="height: 15px; width: 15px;">清除默认头像用户</td></tr></table><h3>深度清粉参数</h3><table style="width: 100%; font-size: 15px;"><tr><td><input id="deepSearchMode" type="checkbox" style="height: 15px; width: 15px;" οnchange="SetDeepSearchParam();">开启深度清粉</td><td> 最小不活跃天数:<input class="DeepSearchParam" id="minDayCount" type="number" style="height: 15px; width: 40px;" min="0" value="180" disabled></td><td><input class="DeepSearchParam" id="ignoreLikes" type="checkbox" style="height: 15px; width: 15px;" checked disabled>无视用户最近点赞</td></tr><tr></tr><tr><td rowspan="2"><input class="DeepSearchParam" id="checkConnection" type="checkbox" style="height: 15px; width: 15px;" disabled>开启检查关注</td><td rowspan="2"> 最小共同关注数:<input class="DeepSearchParam" id="minSameFollowedCount" type="number" style="height: 15px; width: 40px;" min="0" value="3" disabled></td><td><input class="DeepSearchParam" id="ignoreBlueV" type="checkbox" style="height: 15px; width: 15px;" checked disabled>无视蓝V用户</td></tr><tr><td><input class="DeepSearchParam" id="ignoreYellowV" type="checkbox" style="height: 15px; width: 15px;" disabled>无视黄V用户</td></tr></table></div><div class="ready"><button style="position: relative; height: 45px; width:48%; font-size: 16px; margin: 4px 2px;" οnclick="StartRemoveFans();">清粉</button><button style="position: relative; height: 45px; width:48%; font-size: 16px; margin: 4px 2px;" οnclick="StartCheckFans();">检测</button></div><div class="running" style="display: none"><button style="position: relative; height: 45px; width:98%; font-size: 16px; margin: 4px 2px;" οnclick="StopFunc();">停止</button></div><div style="position: relative; margin: 4px 2px; flex-grow: 1; width: 100%; background-color: azure; overflow-y: scroll;"><p class="logger"></p></div><div style="position: absolute; bottom: 0px; height: 1px; width:100%; background-color: black"></div></div><div style="position: fixed; top:0; left: 500px; bottom: 0; right: 0;"><iframe class="web" src="" sandbox="allow-same-origin allow-scripts" style="width:100%; height:100%;"></iframe></div>';
document.body.innerHTML = body.replaceAll('ο','o');let iframe = document.body.querySelector('iframe.web');
iframe.src = window.location.href;
iframe.onload=()=>{ iframe.contentDocument.body.querySelector("div[node-type=outer]")?.remove();}}ReplaceHTML();
版权归原作者 小蛊咕咕 所有, 如有侵权,请联系我们删除。