├── .gitignore ├── icon.png ├── images ├── get_started128.png ├── get_started16.png ├── get_started32.png └── get_started48.png ├── README.md ├── background.js ├── manifest.json ├── popup.html ├── popup.css ├── cycleDeleteWithClick.js ├── popup.js └── getWeiBoList.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengsea/chrome-extensions/HEAD/icon.png -------------------------------------------------------------------------------- /images/get_started128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengsea/chrome-extensions/HEAD/images/get_started128.png -------------------------------------------------------------------------------- /images/get_started16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengsea/chrome-extensions/HEAD/images/get_started16.png -------------------------------------------------------------------------------- /images/get_started32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengsea/chrome-extensions/HEAD/images/get_started32.png -------------------------------------------------------------------------------- /images/get_started48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengsea/chrome-extensions/HEAD/images/get_started48.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chrome-extensions 2 | 3 | chrome 插件 批量删除 微博/粉丝/关注 4 | 5 | batch delete your weibo fans follow 6 | 7 | 1. 下载源码 8 | 2. 安装Chrome浏览器 9 | 3. Chrome浏览器中点击 更多工具-扩展程序     或者直接在URL地址栏中输入 chrome://extensions/ 10 | 4. 选中开发者模式-加载已解压的扩展程序 11 | 5. 选择扩展程序目录 时直接选 源码目录即可 12 | 6. 微博/粉丝/关注页面 点击右上角插件图标 即可开始删除当前页面的微博/粉丝/关注 13 | 14 | - 微博页面url: weibo.com/***/profile 或者 weibo.com/p/***/home 15 | - 粉丝页面url: weibo.com/***/fans 16 | - 关注页面url: weibo.com/***/follow 或者 weibo.com/p/***/myfollow 17 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | 'use strict'; 6 | 7 | chrome.runtime.onInstalled.addListener(function () { 8 | chrome.declarativeContent.onPageChanged.removeRules(undefined, function () { 9 | chrome.declarativeContent.onPageChanged.addRules([{ 10 | conditions: [new chrome.declarativeContent.PageStateMatcher({ 11 | pageUrl: { hostEquals: 'weibo.com' }, 12 | }), 13 | ], 14 | actions: [new chrome.declarativeContent.ShowPageAction()] 15 | }]); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "批量删除微博", 3 | "manifest_version": 2, 4 | "version": "1.2.1", 5 | "description": "批量删除微博/粉丝/关注", 6 | "permissions": [ 7 | "tabs", 8 | "activeTab", 9 | "declarativeContent", 10 | "storage" 11 | ], 12 | "page_action": { 13 | "default_popup": "popup.html", 14 | "default_icon": { 15 | "16": "images/get_started16.png", 16 | "32": "images/get_started32.png", 17 | "48": "images/get_started48.png", 18 | "128": "images/get_started128.png" 19 | } 20 | }, 21 | "background": { 22 | "scripts": [ 23 | "background.js" 24 | ], 25 | "persistent": false 26 | }, 27 | "icons": { 28 | "16": "images/get_started16.png", 29 | "32": "images/get_started32.png", 30 | "48": "images/get_started48.png", 31 | "128": "images/get_started128.png" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 删除面板 8 | 9 | 10 | 11 |

当前页面-

12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 |
34 |
    35 |
    36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | button { 7 | border-radius: 4px; 8 | color: #fff; 9 | background-color: #0C8EE8; 10 | width: 200px; 11 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); 12 | box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); 13 | height: 40px; 14 | font-size: 16px; 15 | font-weight: 400; 16 | line-height: 1; 17 | border: 1px solid #1890ff; 18 | cursor: pointer; 19 | } 20 | 21 | 22 | label { 23 | font-size: 16px; 24 | } 25 | 26 | .weiboLists { 27 | width: 700px; 28 | padding-left: 30px; 29 | } 30 | 31 | #weiboList { 32 | padding: 0 0 0 30px; 33 | padding-inline-start: 0; 34 | display: flex; 35 | flex-direction: column; 36 | } 37 | 38 | li { 39 | float: left; 40 | } 41 | 42 | li div { 43 | float: right; 44 | width: 640px; 45 | } 46 | 47 | .method { 48 | display: flex; 49 | align-items: center; 50 | } 51 | 52 | .method div { 53 | margin-right: 10px; 54 | } 55 | -------------------------------------------------------------------------------- /cycleDeleteWithClick.js: -------------------------------------------------------------------------------- 1 | //循环点击按钮删除 2 | for (let i = 0, 3 | len = 4 | location.pathname.includes('home') ? document.querySelectorAll('.WB_cardwrap.WB_feed_type.S_bg2.WB_feed_like').length : 5 | location.pathname.includes('profile') ? document.querySelectorAll('.WB_cardwrap.WB_feed_type.S_bg2.WB_feed_like').length : 6 | location.pathname.includes('fans') ? document.querySelectorAll('.follow_item.S_line2').length: 7 | location.pathname.includes('follow') ? document.getElementsByClassName('member_li S_bg1').length: 0 8 | ; i < len; i++) { 9 | setTimeout(batchClick, 2000 * i); 10 | } 11 | 12 | function batchClick() { 13 | if (location.pathname.includes('home')||location.pathname.includes('profile')) {//我的主页 14 | document.querySelector('a[action-type="fl_menu"]').click(); 15 | document.querySelector('a[title="删除此条微博"]').click(); 16 | document.querySelector('a[action-type="ok"]').click(); 17 | } else if (location.pathname.includes('fans')) {//粉丝 18 | document.querySelector('div[node-type="layer_menu_list"]').style.display='block'; 19 | document.querySelector('a[action-type="removeFan"]').click(); 20 | document.querySelector('.W_btn_a').click(); 21 | } else if (location.pathname.includes('follow')) {//我的关注 22 | document.querySelector('div[node-type="layer_hover_list"]').style.display='block'; 23 | document.querySelector('a[action-type="cancel_follow_single"]').click(); 24 | document.querySelector('.W_btn_a').click(); 25 | } 26 | 27 | chrome.runtime.sendMessage({ type: "deleteByClickFinish" }); 28 | } 29 | 30 | //@ sourceURL=cycleDeleteWithClick.js 31 | -------------------------------------------------------------------------------- /popup.js: -------------------------------------------------------------------------------- 1 | let triggerDelete = document.getElementById('triggerDelete');//事件删除按钮 2 | let postDelete = document.getElementById('postDelete');//接口删除按钮 3 | let weiboList = document.getElementById('weiboList');//列表 4 | let selectAll = document.getElementById('selectAll');//全选 5 | let triggerDeleteCount = 0, 6 | postDeleteCount = 0, 7 | weiboSource = [], 8 | weiboSet = new Set();//删除的条数 9 | 10 | triggerDelete.onclick = function () { 11 | chromeTabs('cycleDeleteWithClick.js'); 12 | }; 13 | selectAll.onclick = function (element) { 14 | if (element.target.checked) {//选中 15 | weiboSource.forEach(item => weiboSet.add(item.mid)); 16 | document.querySelectorAll('#weiboList input').forEach(item => item.checked = true); 17 | } else {//未选中 18 | weiboSet = new Set(); 19 | document.querySelectorAll('#weiboList input').forEach(item => item.checked = false); 20 | } 21 | }; 22 | postDelete.onclick = function () { 23 | //发送删除消息 24 | chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { 25 | chrome.tabs.sendMessage(tabs[0].id, {type: "deleteMid", data: [...weiboSet]}, function (response) { 26 | 27 | }); 28 | }); 29 | }; 30 | 31 | chromeTabs('getWeiBoList.js'); 32 | 33 | //显示当前的列表 34 | function draw(data) { 35 | data.map((item, index) => { 36 | let li = document.createElement('li'); 37 | // li.innerText = (index + 1) + ' . ' + item.text; 38 | li.className = 'mid_' + item.mid; 39 | 40 | let label = document.createElement('label'); 41 | 42 | let input = document.createElement('input'); 43 | input.attributes['mid'] = item.mid; 44 | input.attributes['id'] = item.mid; 45 | input.onclick = (e) => changeSet(e, item.mid); 46 | input.type = 'checkbox'; 47 | label.appendChild(input); 48 | label.appendChild(document.createTextNode(item.text)); 49 | li.appendChild(label); 50 | 51 | weiboList.appendChild(li); 52 | }); 53 | } 54 | 55 | //勾选 56 | function changeSet(e, mid) { 57 | if (e.target.checked) { 58 | weiboSet.add(mid); 59 | } else { 60 | weiboSet.delete(mid); 61 | } 62 | } 63 | 64 | //当前活动的页面执行js 65 | function chromeTabs(file) { 66 | chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { 67 | chrome.tabs.executeScript( 68 | tabs[0].id, 69 | {file}); 70 | }); 71 | } 72 | 73 | chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { 74 | document.getElementById('pageName').innerText = tabs[0].url.includes('fans') ? '我的粉丝' : tabs[0].url.includes('follow') ? '我的关注' : '我的微博'; 75 | }); 76 | 77 | chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { 78 | switch (request.type) { 79 | case 'deleteByClickFinish'://点击删除事件 80 | triggerDeleteCount++; 81 | document.getElementById('triggerDeleteCount').innerText = triggerDeleteCount+''; 82 | break; 83 | case 'getList'://获得列表 84 | weiboSource = request.data; 85 | draw(request.data); 86 | break; 87 | case 'deleteMidCallback'://获得列表 88 | postDeleteCount++; 89 | document.getElementById('postDeleteCount').innerText = postDeleteCount+''; 90 | weiboList.removeChild(document.querySelector(`.mid_${request.data}`)); 91 | sendResponse({farewell: "ok"}); 92 | break; 93 | default: 94 | console.log('错误的类型'); 95 | } 96 | }); 97 | -------------------------------------------------------------------------------- /getWeiBoList.js: -------------------------------------------------------------------------------- 1 | const page = location.pathname.includes('home') || location.pathname.includes('profile') ? 0 : 2 | location.pathname.includes('fans') ? 1 : 3 | location.pathname.includes('follow') ? 2 : 3; 4 | 5 | //获取数据列表 6 | function getList() { 7 | let arr = []; 8 | if (location.pathname.includes('home') || location.pathname.includes('profile')) {//我的主页 9 | let listItemList = document.querySelectorAll('div[action-type="feed_list_item"]'); 10 | for (let i = 0; i < listItemList.length; i++) { 11 | let item = listItemList[i]; 12 | let mid = item.attributes['mid'].value; 13 | let contentText = item.querySelector('div[node-type=feed_list_content]').innerText; 14 | arr.push({ 15 | mid, 16 | text: contentText 17 | }) 18 | } 19 | } else if (location.pathname.includes('fans')) {//我的粉丝 20 | let listItemList = document.querySelectorAll('.follow_item.S_line2'); 21 | for (let i = 0, len = listItemList.length; i < len; i++) { 22 | let item = listItemList[i]; 23 | let action = item.attributes['action-data'].value; 24 | let actions = action.split('&'); 25 | arr.push({ 26 | mid: actions[0].split('=')[1], 27 | text: actions[1].split('=')[1] 28 | }) 29 | } 30 | } else if (location.pathname.includes('follow')) {//我的关注 31 | let listItemList = document.getElementsByClassName('member_li S_bg1'); 32 | for (let item of listItemList) { 33 | let actions = item.attributes['action-data'].value.split('&'); 34 | let mid, text; 35 | for (let action of actions) { 36 | if (action.startsWith('uid')) { 37 | mid = action.split('=')[1] 38 | } else if (action.startsWith('screen_name')) { 39 | text = action.split('=')[1] 40 | } 41 | } 42 | 43 | arr.push({mid, text}) 44 | } 45 | } 46 | 47 | return arr; 48 | } 49 | 50 | //发送消息-列表数据 51 | chrome.runtime.sendMessage({type: 'getList', data: getList()}, function (response) { 52 | console.log(response.farewell); 53 | }); 54 | 55 | //接受消息 56 | chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { 57 | switch (request.type) { 58 | case 'deleteMid'://post删除 59 | deleteMid(request.data); 60 | break; 61 | default: 62 | console.log('错误的类型'); 63 | } 64 | }); 65 | 66 | function deleteMid(data) { 67 | if (Array.isArray(data)) { 68 | for (let i = 0; i < data.length; i++) { 69 | // setTimeout(()=>deleteMidItem(data[ i ]), 2000 * i); 70 | deleteMidItem(data[i]); 71 | } 72 | } else { 73 | deleteMidItem(data); 74 | } 75 | //删除完成后点击tab刷新 76 | setTimeout(function () { 77 | if (page === 2) { 78 | document.getElementsByClassName('lev_a current S_bg1')[0].click(); 79 | } else 80 | document.querySelector('.WB_tab_b .S_line1').click(); 81 | },2000); 82 | 83 | } 84 | 85 | function deleteMidItem(mid) { 86 | let path = 'aj/f/remove';//删除url路径 87 | if (page === 2) { 88 | path = 'aj/f/unfollow' 89 | } 90 | let xhr = new XMLHttpRequest(); 91 | xhr.open('POST', `https://weibo.com/${path}?ajwvr=6`); 92 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 93 | xhr.send(encodeURI('uid=' + mid)); 94 | // xhr.send(encodeURI('fname=' + mid));//微博多余的参数 95 | // xhr.send(encodeURI('fnick=' + mid)); 96 | // xhr.send(encodeURI('_t=' + 0)); 97 | xhr.onreadystatechange = () => { 98 | if (xhr.readyState === 4) {//4代表执行完成 99 | if (xhr.status === 200) {//200代表执行成功 100 | chrome.runtime.sendMessage({type: 'deleteMidCallback', data: mid}, function () { 101 | console.log(eval("'" + xhr.responseText + "'")); 102 | }); 103 | 104 | } 105 | } 106 | }; 107 | } 108 | 109 | //@ sourceURL=getWeiBoList.js 110 | --------------------------------------------------------------------------------