Skip to content

Instantly share code, notes, and snippets.

@lewangdev
Last active July 3, 2023 13:17
Show Gist options
  • Save lewangdev/03c70accaabb10ba9cbb86c86d0c6602 to your computer and use it in GitHub Desktop.
Save lewangdev/03c70accaabb10ba9cbb86c86d0c6602 to your computer and use it in GitHub Desktop.

Revisions

  1. lewangdev revised this gist Jul 3, 2023. 2 changed files with 0 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
  2. lewangdev revised this gist Jul 3, 2023. 2 changed files with 42 additions and 4 deletions.
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    let followerIdsArray = Array.from(followerIds);

    // 存储到localStorage
    localStorage.setItem('followerIds', JSON.stringify(followerIdsArray));
    localStorage.setItem('MyFollowingIds', JSON.stringify(followerIdsArray));
    }

    function saveAsCSV(username) {
    @@ -18,7 +18,7 @@
    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", `${username}-followerIds.csv`);
    link.setAttribute("download", `${username}-MyFollowingIds.csv`);
    document.body.appendChild(link); // 为了在 Firefox 中工作,需要将链接添加到文档中

    // 自动点击链接进行下载
    @@ -76,10 +76,10 @@
    clearInterval(intervalID);
    saveAsLocalStorage(username);
    saveAsCSV(username);
    console.log("Stopped scrolling. Final follower IDs:", followerIds);
    console.log("MyFollowing: Stopped scrolling. Final follower IDs:", followerIds);
    }
    } else {
    console.log(followerIds);
    console.log("MyFollowing: Current follower IDs:", followerIds);
    previousSize = followerIds.size; // 更新Set的大小
    noChangeCount = 0; // 重置没有变化的次数
    }
    38 changes: 38 additions & 0 deletions Step-2-AddFollowingToList.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    (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);
  3. lewangdev renamed this gist Jul 3, 2023. 1 changed file with 9 additions and 0 deletions.
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,12 @@
    (function(window) {
    function saveAsLocalStorage(username) {
    // 将 Set 转换为 Array
    let followerIdsArray = Array.from(followerIds);

    // 存储到localStorage
    localStorage.setItem('followerIds', JSON.stringify(followerIdsArray));
    }

    function saveAsCSV(username) {
    // 将 Set 转换为 Array
    let followerIdsArray = Array.from(followerIds);
    @@ -66,6 +74,7 @@
    noChangeCount += 1;
    if (noChangeCount >= maxNoChangeCount) {
    clearInterval(intervalID);
    saveAsLocalStorage(username);
    saveAsCSV(username);
    console.log("Stopped scrolling. Final follower IDs:", followerIds);
    }
  4. lewangdev revised this gist Jul 2, 2023. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions getTwitterUserFollowingListAsCsv.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    (function(window) {
    function saveAsCSV() {
    function saveAsCSV(username) {
    // 将 Set 转换为 Array
    let followerIdsArray = Array.from(followerIds);

    @@ -10,7 +10,7 @@
    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "followerIds.csv");
    link.setAttribute("download", `${username}-followerIds.csv`);
    document.body.appendChild(link); // 为了在 Firefox 中工作,需要将链接添加到文档中

    // 自动点击链接进行下载
    @@ -66,7 +66,7 @@
    noChangeCount += 1;
    if (noChangeCount >= maxNoChangeCount) {
    clearInterval(intervalID);
    saveAsCSV();
    saveAsCSV(username);
    console.log("Stopped scrolling. Final follower IDs:", followerIds);
    }
    } else {
    @@ -78,4 +78,4 @@
    window.scrollBy(0, scrollByVerticalInPixel);
    }, 1000);
    }
    })(window);
    })(window);
  5. lewangdev created this gist Jul 2, 2023.
    81 changes: 81 additions & 0 deletions getTwitterUserFollowingListAsCsv.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    (function(window) {
    function saveAsCSV() {
    // 将 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", "followerIds.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);
    saveAsCSV();
    console.log("Stopped scrolling. Final follower IDs:", followerIds);
    }
    } else {
    console.log(followerIds);
    previousSize = followerIds.size; // 更新Set的大小
    noChangeCount = 0; // 重置没有变化的次数
    }
    // 无论是否发生变化,都滚动页面
    window.scrollBy(0, scrollByVerticalInPixel);
    }, 1000);
    }
    })(window);