用到的库:
wechaty
: 一个用于开发微信聊天机器人的框架。
qrcode-terminal
: 用于生成终端二维码的库。
xlsx
: 用于处理 Excel 文件的库。
fs
和 path
: 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();
发表回复