├── .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 |
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 |
--------------------------------------------------------------------------------