Last active
July 3, 2023 13:17
-
-
Save lewangdev/03c70accaabb10ba9cbb86c86d0c6602 to your computer and use it in GitHub Desktop.
Get Twitter followings and add them to your private list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(window) { | |
function saveAsLocalStorage(username) { | |
// 将 Set 转换为 Array | |
let followerIdsArray = Array.from(followerIds); | |
// 存储到localStorage | |
localStorage.setItem('MyFollowingIds', JSON.stringify(followerIdsArray)); | |
} | |
function saveAsCSV(username) { | |
// 将 Set 转换为 Array | |
let followerIdsArray = Array.from(followerIds); | |
// 构造 CSV 字符串 | |
let csvContent = "data:text/csv;charset=utf-8," + followerIdsArray.join("\n"); | |
// 创建隐藏的可下载链接 | |
var encodedUri = encodeURI(csvContent); | |
var link = document.createElement("a"); | |
link.setAttribute("href", encodedUri); | |
link.setAttribute("download", `${username}-MyFollowingIds.csv`); | |
document.body.appendChild(link); // 为了在 Firefox 中工作,需要将链接添加到文档中 | |
// 自动点击链接进行下载 | |
link.click(); | |
} | |
// 创建一个Set,用于存储followerId,避免重复 | |
let followerIds = new Set(); | |
// 获取当前页面的URL | |
let currentURL = window.location.href; | |
// 解析URL以获取用户名 | |
let urlParts = currentURL.split("/"); | |
let username = urlParts.length > 3 ? urlParts[3] : null; | |
// 构造需要的URL | |
let targetURL = `https://twitter.com/${username}/following`; | |
// 检查当前页面的URL | |
if (currentURL === targetURL) { | |
// 当前页面是指定的页面,执行收集followerId的逻辑 | |
function getFollowerIds() { | |
var divs = document.querySelectorAll('div[aria-label="Timeline: Following"]'); | |
divs.forEach(function(div) { | |
var followers = div.querySelectorAll('a[role="link"]'); | |
for (var i = 0; i < followers.length; i++) { | |
var span = followers[i].querySelector('span'); // 在每个 a 标签中查找 span 标签 | |
if (span) { // 如果找到了 span 标签 | |
var id = span.textContent; // 获取 span 标签的文本内容 | |
if (id.startsWith('@')) { // 如果文本内容以 @ 开头 | |
var followerId = id.substring(1); // 从文本内容中提取 follower ID(去掉开头的 @) | |
followerIds.add(followerId); // 注意这里应该添加 followerId 而不是 id | |
} | |
} | |
} | |
}); | |
} | |
// 监听滚动事件 | |
window.addEventListener('scroll', getFollowerIds); | |
// 每隔一秒滚动一定的距离,并输出收集到的 followerIds | |
let scrollByVerticalInPixel = 500; | |
let previousSize = -1; // 初始化Set的大小为 -1 | |
let noChangeCount = 0; // 初始化没有变化的次数为 0 | |
let maxNoChangeCount = 50; // 达到最大相同次数就退出 | |
let intervalID = setInterval(() => { | |
// 如果Set的大小在连续maxNoChangeCount次检查中都没有变化,则清除定时器 | |
if (followerIds.size === previousSize) { | |
noChangeCount += 1; | |
if (noChangeCount >= maxNoChangeCount) { | |
clearInterval(intervalID); | |
saveAsLocalStorage(username); | |
saveAsCSV(username); | |
console.log("MyFollowing: Stopped scrolling. Final follower IDs:", followerIds); | |
} | |
} else { | |
console.log("MyFollowing: Current follower IDs:", followerIds); | |
previousSize = followerIds.size; // 更新Set的大小 | |
noChangeCount = 0; // 重置没有变化的次数 | |
} | |
// 无论是否发生变化,都滚动页面 | |
window.scrollBy(0, scrollByVerticalInPixel); | |
}, 1000); | |
} | |
})(window); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(window) { | |
// 定义一个异步的添加函数 | |
async function addById(id) { | |
// 填充输入框并触发 change 事件 | |
let nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; | |
let changeEvent = new Event('change', { bubbles: true}); | |
let inputBox = document.querySelector('input[aria-label="Search query"]'); | |
nativeInputValueSetter.call(inputBox, id); | |
inputBox.dispatchEvent(changeEvent); | |
// 等待一段时间,让页面有机会更新 | |
await new Promise(resolve => setTimeout(resolve, 2000)); | |
// 点击“添加”按钮 | |
let addButton = document.querySelector('div[role="button"][aria-label="Add"]'); | |
if (addButton) { | |
addButton.click(); | |
} | |
// 再等待一段时间,让页面有机会更新 | |
await new Promise(resolve => setTimeout(resolve, 2000)); | |
} | |
// 从 localStorage 获取 ID 列表 | |
let storedIds = JSON.parse(localStorage.getItem('MyFollowingIds')) || []; | |
// 按顺序添加所有 ID | |
async function addAllIds() { | |
for (let id of storedIds) { | |
await addById(id); | |
} | |
} | |
// 开始执行 | |
addAllIds(); | |
})(window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment