【Node.js】批量导出微信联系人到Excel表格(基于Wechaty)

用到的库:

wechaty: 一个用于开发微信聊天机器人的框架。

qrcode-terminal: 用于生成终端二维码的库。

xlsx: 用于处理 Excel 文件的库。

fspath: Node.js 的内置文件系统模块,用于文件操作。

file-box: 用于处理文件(如图片)的库。

uuid: 用于生成唯一标识符(UUID)的库。

工作原理:

基于wechaty的api,获取相应信息并批量导出到excel表格中,头像文件夹单独放置。可以在WPS中依靠UUID生成的唯一ID来快速批量嵌入头像。

可惜标签功能不在Wechaty的功能中,也没法导出手机号等更有价值的信息,目前能导出的信息不多,图一乐。

const { WechatyBuilder } = require('wechaty');
const qrcode = require('qrcode-terminal');
const xlsx = require('xlsx');
const fs = require('fs');
const path = require('path');
const { FileBox } = require('file-box');
const { v4: uuidv4 } = require('uuid');  // 引入 UUID 库

const outputDir = './avatars/';  // 存储头像的文件夹

// 确保头像目录存在
if (!fs.existsSync(outputDir)) {
  fs.mkdirSync(outputDir);
}

class WeChaty {
  bot = null;

  constructor() {
    this.bot = WechatyBuilder.build();
    this.bot.on('scan', code => {
      qrcode.generate(code, { small: true });
    });
    this.bot.on('login', user => {
      console.log(`登录成功,欢迎 ${user}`);
      this.waitForContacts();  // 登录后开始等待联系人同步
    });
  }

  // 随机延时函数,返回一个 Promise,用于模拟短时延时
  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  // 每10秒检查一次联系人数量,最多检查10次
  async waitForContacts() {
    let previousCount = 0;
    let currentCount = 0;
    let attempts = 0;

    while (attempts < 10) {
      const allContacts = await this.bot.Contact.findAll();  // 获取所有联系人
      currentCount = allContacts.length;

      if (currentCount === previousCount) {
        console.log('联系人数量没有变化,开始导出');
        break;  // 如果联系人数量没有变化,则认为同步完成
      }

      console.log(`当前联系人数量: ${currentCount}, 尝试次数: ${attempts + 1}`);
      previousCount = currentCount;
      attempts++;

      await this.delay(10000);  // 每次等待10秒再检查
    }

    if (attempts >= 10) {
      console.log('尝试多次后联系人数量没有变化,开始导出');
    }

    // 导出联系人
    this.getAllFriendContacts();
  }

  // 获取所有好友联系人
  async getAllFriendContacts() {
    const allContacts = await this.bot.Contact.findAll();  // 获取所有联系人

    // 只筛选出好友联系人
    const friendContacts = allContacts.filter(contact => 
      contact.friend() && contact.type() === this.bot.Contact.Type.Individual
    );

    console.log(`总共获取了 ${friendContacts.length} 个好友联系人`);

    if (friendContacts.length > 0) {
      await this.exportContacts(friendContacts);  // 导出好友联系人
    }
  }

  // 获取并保存联系人头像
  async saveAvatar(contact) {
    try {
      const avatarFile = await contact.avatar();
      if (avatarFile) {
        const cleanName = contact.name().replace(/[\/\\:*?"<>|]/g, '_');  // 清理非法字符
        const uniqueName = `${cleanName}_${uuidv4()}`;  // 使用清理后的昵称 + UUID 作为文件名
        const avatarPath = path.join(outputDir, uniqueName + '.jpg');  // 存储路径

        await avatarFile.toFile(avatarPath, true);  // 保存头像文件
        return uniqueName;  // 返回不带后缀的文件名
      }
    } catch (error) {
      console.log(`获取 ${contact.name()} 头像失败`);
    }
    return '';  // 如果获取失败,返回空字符串
  }

  // 导出联系人信息
  async exportContacts(allContacts) {
    try {
      const contactList = [];

      const avatarPromises = allContacts.map(async (contact) => {
        // 获取头像文件名
        const avatarFileName = await this.saveAvatar(contact);  

        // 只导出有头像的联系人,且即使没有昵称也会保留
        return {
          昵称: contact.name().trim() || '无昵称',  // 如果没有昵称,则使用 '无昵称'
          备注: (await contact.alias())?.trim() || '',  // 获取备注信息
          性别: contact.gender() === this.bot.Contact.Gender.Male ? '男' : 
                contact.gender() === this.bot.Contact.Gender.Female ? '女' : '未知',  // 性别
          省份: contact.province()?.trim() || '',  // 获取省份
          城市: contact.city()?.trim() || '',  // 获取城市
          文件名: avatarFileName,  // 保存文件名(不带后缀)
        };
      });

      // 等待所有头像保存完毕
      const contactData = await Promise.all(avatarPromises);

      // 使用 xlsx 库导出 Excel 表格
      const ws = xlsx.utils.json_to_sheet(filteredContactData);  // 将联系人信息转换为 Excel 表格
      const wb = xlsx.utils.book_new();  // 创建一个新的 Excel 工作簿
      xlsx.utils.book_append_sheet(wb, ws, '联系人');  // 将联系人数据添加到工作簿

      // 将工作簿保存为 Excel 文件
      xlsx.writeFile(wb, 'contacts_with_details.xlsx');
      console.log('好友联系人信息已成功导出到 contacts_with_details.xlsx');
    } catch (error) {
      console.error('导出联系人信息失败:', error);
    }
  }

  run() {
    this.bot.start();
  }
}

new WeChaty().run();

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注