# 方法一:分段提取,手动合并

由于微博采用 “虚拟滚动” (Virtual Scroller) 技术所以我们采用分段提取,手动合并的方法。
需要将脚本拆分为三部分:1. 初始化 -> 2. 循环提取 -> 3. 最终导出

# 操作流程

  1. 【仅执行一次】 在控制台粘贴并运行 “ 代码1 ”,初始化一个数据仓库。
  2. 现在,开始 慢慢向下滚动页面
  3. 每滚动一两屏,就粘贴并运行 “ 代码2 ”。你会看到控制台打印出新增了多少用户。
  4. 重复第 3 步, 滚动一点,运行一次代码2 ,直到滚动到列表的最底部,出现 “没有更多数据了” 的提示。
  5. 【仅执行一次】 确认你已滚动到底部,最后在控制台粘贴并运行 “ 代码3 ”,生成并下载包含所有人的 CSV 文件。

在微博关注列表页面按 F12 打开开发者工具,点击 “控制台” (Console) 运行代码。

# 代码 1:初始化数据仓库 (只在最开始运行一次)

// 代码 1:初始化
window.myFollowingList = []; // 用来存储最终结果
window.myFollowingLinks = new Set(); // 用来去重,确保每个用户只添加一次
console.log("✅ 初始化完成!已创建数据仓库。现在可以开始滚动并使用“代码2”进行提取了。");

# 代码 2:提取当前可见用户 (滚动时反复运行)

// 代码 2:提取当前屏幕可见的用户
const CARD_SELECTOR = '.UserFeedCard_userFeedCard_3shKr';
const LINK_SELECTOR = 'a.UserFeedCard_left_2XXOA';
const NICKNAME_SELECTOR = '.UserFeedCard_cla_1QH69 > span';
const userCards = document.querySelectorAll(CARD_SELECTOR);
let newCount = 0;
userCards.forEach(card => {
    const linkElement = card.querySelector(LINK_SELECTOR);
    if (linkElement && linkElement.href) {
        const userLink = new URL(linkElement.href, window.location.origin).href;
        
        // 使用 Set 来判断是否是新用户
        if (!window.myFollowingLinks.has(userLink)) {
            const nicknameElement = card.querySelector(NICKNAME_SELECTOR);
            const nickname = nicknameElement ? nicknameElement.innerText.trim() : '未知昵称';
            window.myFollowingLinks.add(userLink);
            window.myFollowingList.push({ nickname: nickname, link: userLink });
            newCount++;
        }
    }
});
console.log(`🔎 本次提取新增 ${newCount} 个用户。当前总计 ${window.myFollowingList.length} 个用户。请继续滚动并运行本脚本。`);

# 代码 3:导出所有数据 (滚动到底部后,最后运行一次)

// 代码 3:生成并下载 CSV
if (!window.myFollowingList || window.myFollowingList.length === 0) {
    console.error("❌ 错误:数据仓库为空,无法导出。请确认您已运行过代码1和代码2。");
} else {
    console.log(`🚀 即将导出全部分类,总计 ${window.myFollowingList.length} 个用户。`);
    let csvContent = "序号,用户昵称,个人主页链接\n";
    window.myFollowingList.forEach((user, index) => {
        const safeNickname = user.nickname.replace(/"/g, '""');
        csvContent += `${index + 1},"${safeNickname}","${user.link}"\n`;
    });
    const blob = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);
    link.setAttribute("href", url);
    link.setAttribute("download", `my_weibo_followings_total_${window.myFollowingList.length}.csv`);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    console.log("✅ 下载完成!");
}

# 方法二:全自动微博关注列表 API 导出脚本 - 简介与使用说明

# 脚本功能

本脚本用于快速、完整地导出指定微博用户(通常是您自己)的全部关注列表,并将其自动保存为一个 .csv 格式的表格文件。该文件可以用 Excel、WPS 表格或任何文本编辑器打开。

# 核心原理与优势

  • 高效稳定:脚本通过直接调用微博的官方数据接口(API)来获取列表,而非模拟人工在页面上滚动。因此,它的执行速度极快,可以轻松导出数千人的列表,且过程非常稳定。

  • 完整无遗漏:此方法能完美绕过微博主页的 “虚拟滚动” 技术限制,确保可以获取到关注列表中的每一个人,不会像滚动脚本那样出现数据遗漏。

  • 高成功率:由于是直接与数据接口交互,大大减少了对微博服务器的请求次数,能有效避免因操作频繁而被临时限制访问的问题。

  • 数据清晰:导出的 CSV 文件包含序号、用户昵称、用户 UID 以及自动为您拼接好的个人主页链接,方便您后续整理和使用。

# 使用前准备

  • 核心要求:运行此脚本前,您必须手动找到您自己的微博 UID(一串代表您身份的数字)。

# 如何使用

  1. 获取您的 UID:
  • 登录微博,进入您自己的个人主页。

  • 查看浏览器顶部的地址栏。链接通常会是 https://weibo.com/u/1234567890 的格式。

  • 其中,u/ 后面的那一长串数字(例如 1234567890)就是您的 UID。请将其复制下来。

  1. 配置脚本:
  • 复制脚本的完整代码。

  • 找到代码最顶部的配置区,将您刚刚复制的 UID 粘贴到 yourUid 变量的引号内,替换掉原来的示例数字。

// 例如,修改为:
const yourUid = "1234567890";
  1. 运行脚本:
  • 在任意一个微博页面上(只要是 weibo.com 的域名下即可),按 F12 键打开 “开发者工具”。

  • 点击 “控制台” (Console) 选项卡。

  • 将您修改好的完整代码粘贴进去,然后按 回车键。

  1. 下载文件:
  • 脚本会自动开始执行,您可以在控制台看到它的运行进度。

  • 任务完成后,浏览器将自动下载一个名为 微博关注列表_XXX 人.csv 的文件,导出成功!

# 重要提示

本脚本依赖于微博当前的 API 接口设计。如果未来微博的工程师对其进行了修改(例如更改 API 地址、参数或返回的数据结构),此脚本可能会失效。届时,就需要重新进行 “网络侦测”,找到新的 API 信息来更新脚本。

# 全自动脚本

async function exportFollowingsWithManualUID() {
    // —————————— ▼▼▼【请在这里配置】▼▼▼ ——————————
    // 1. 请在这里填入您自己的 UID(那串数字)。请保留双引号。
    const yourUid = "1234567890"; 
    // —————————— ▲▲▲【配置完成】▲▲▲ ——————————
    //--- 检查配置是否已修改 ---
    if (yourUid === "1234567890") {
        console.error("❌ 请先修改脚本中的 yourUid,填入您自己的UID!");
        return;
    }
    console.log("🚀 手动配置模式启动!");
    console.log(`✅ 已指定UID: ${yourUid}`);
    //--- 脚本核心逻辑 ---
    const baseUrl = "https://weibo.com/ajax/profile/followContent";
    const masterList = new Map();
    let page = 1;
    let nextCursor = "0";
    let hasMore = true;
    while (hasMore) {
        try {
            const apiUrl = `${baseUrl}?page=${page}&next_cursor=${nextCursor}&uid=${yourUid}`;
            console.log(`正在请求第 ${page} 页 (cursor: ${nextCursor})...`);
            
            const response = await fetch(apiUrl);
            if (!response.ok) throw new Error(`网络请求失败,状态码: ${response.status}`);
            
            const data = await response.json();
            if (!data.ok || data.ok !== 1) throw new Error(data.msg || "API返回错误状态");
            
            const users = data.data?.follows?.users;
            if (!users || users.length === 0) {
                console.log("ℹ️ API返回的用户列表为空,已到达列表末尾。");
                hasMore = false;
                continue;
            }
            let newCountInPage = 0;
            for (const user of users) {
                if (user && user.id && !masterList.has(user.id.toString())) {
                    const nickname = user.screen_name?.trim() || '未知昵称';
                    masterList.set(user.id.toString(), nickname);
                    newCountInPage++;
                }
            }
            console.log(`✅ 第 ${page} 页处理完毕,新增 ${newCountInPage} 个用户。当前总数: ${masterList.size}`);
            
            page++;
            nextCursor = data.data?.follows?.next_cursor?.toString() || "0";
            if (nextCursor === "0" || newCountInPage === 0) hasMore = false;
            await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 500)); 
        } catch (error) {
            console.error(`❌ 在请求第 ${page} 页时发生严重错误:`, error.message);
            console.error("脚本已中断。");
            hasMore = false;
        }
    }
    if (masterList.size === 0) {
        console.warn("⚠️ 任务完成,但未能收集到任何用户数据。");
        return;
    }
    //--- 生成并下载 CSV 文件 ---
    console.log(`🚀 数据全部获取完毕!总计 ${masterList.size} 个用户。准备生成CSV文件...`);
    let csvContent = "序号,用户昵称,用户UID,个人主页链接\n";
    let index = 1;
    for (const [uid, nickname] of masterList.entries()) {
        const safeNickname = nickname.replace(/"/g, '""');
        const userLink = `https://weibo.com/u/${uid}`;
        csvContent += `${index++},"${safeNickname}","${uid}","${userLink}"\n`;
    }
    const blob = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);
    link.setAttribute("href", url);
    link.setAttribute("download", `微博关注列表_${masterList.size}人.csv`);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    console.log("✅ 下载完成!");
}
// 自动运行主函数
exportFollowingsWithManualUID();
更新于