前言:管理多个三角洲账号时,手动逐个登录查信息效率极低。本文介绍一套基于 Node.js 的自动化查询方案——先用pi.js获取账号的 openid,再用openidQuery.js批量拉取角色名、等级、金币、资产等核心数据,最终一键导出到 Excel。
一、项目概述
本项目由两个脚本配合使用,缺一不可:
| 脚本 | 作用 | 使用顺序 |
|---|---|---|
pi.js | 调用 WeGame 接口,获取当前登录账号的 openid | ① |
openidQuery.js | 读取 openid 列表,批量查询多账号数据并写入 Excel | ② |
工作流程:
登录 WeGame → 运行 pi.js → 拿到 openid ↓ 写入 openid.txt(可多账号) ↓ 运行 openidQuery.js → 批量查询 → 导出 Excel最终可查询到的字段:角色名、等级、金币(K/M 格式化)、账号资产、最后登出时间、是否封禁
二、环境准备
安装 Node.js
确保本地已安装 Node.js(建议 v16+):
node -v npm -v安装依赖
npm install request xlsx exceljs| 依赖包 | 用途 |
|---|---|
request | 发送 HTTP 请求 |
xlsx | Excel 文件基础处理 |
exceljs | 读写 Excel,保留原有格式 |
目录结构
project/ ├── config/ │ ├── openid.txt # openid 账号列表(由 pi.js 结果手动填入) │ └── output.xlsx # 输出 Excel(需提前创建模板) ├── pi.js # Step 1:获取 openid └── openidQuery.js # Step 2:批量查询并导出三、完整代码
pi.js(获取 openid)
javascript
const cookie = '(https://www.wegame.com.cn/helper/df/score/)里获取' var request = require('request'); var options = { 'method': 'POST', 'url': 'https://www.wegame.com.cn/api/v1/wegame.pallas.dfm.DfmBattle/GetRoleInfo', 'headers': { 'referer': 'https://www.wegame.com.cn/helper/df/score/', 'Cookie': cookie, 'Content-Type': 'application/json' }, body: JSON.stringify({ "from_src": "df_web", "account_type": 1, "area": 36 }) }; request(options, function (error, response) { if (error) throw new Error(error); console.log(response.body); });openidQuery.js(批量查询 + 导出 Excel)
const request = require('request'); const fs = require('fs'); const path = require('path'); const XLSX = require('xlsx'); const ExcelJS = require('exceljs'); const cookie = '(https://df.qq.com/cp/a20240906main/index.html)里获取'; const txtPath = path.resolve(__dirname, './config/openid.txt'); const lines = fs.readFileSync(txtPath, 'utf-8').trim().split('\n'); const accounts = lines .map(line => { const parts = line.trim().split(/\s+/); return { qq: parts[0], openid: parts[1] }; }) .filter(a => a.openid && a.openid !== 'null'); function formatNum(val) { const n = Number(val); if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + 'M'; if (n >= 1_000) return (n / 1_000).toFixed(1) + 'K'; return n; } function queryOne(account) { return new Promise((resolve) => { const url = `https://comm.ams.game.qq.com/ide/?iChartId=369172&iSubChartId=369172&sIdeToken=FDNRsR&source=5&sArea=36&openid=${account.openid}¶m={"source":"5","openid":"${account.openid}"}`; request( { method: 'POST', url, headers: { Cookie: cookie, 'content-type': 'application/x-www-form-urlencoded;' } }, (error, response) => { if (error) { console.error(`[${account.qq}] 请求失败:`, error.message); return resolve(null); } try { const resData = JSON.parse(response.body); if (resData.ret === 0 && resData.jData?.data) { const d = resData.jData.data; const row = { QQ号: account.qq, 角色名: decodeURIComponent(d.charac_name), 等级: d.level, 金币: formatNum(d.hafcoinnum), 资产: formatNum(d.propcapital), 最后登出: new Date(d.lastlogouttime * 1000).toLocaleString(), 是否封禁: d.isbanuser === '1' ? '是' : '否', }; console.log(`[OK] ${row.角色名} | 等级 ${row.等级} | 金币 ${row.金币}`); resolve(row); } else { console.log(`[${account.qq}] 查询失败:`, resData.sMsg); resolve(null); } } catch (e) { console.error(`[${account.qq}] 解析失败:`, e.message); resolve(null); } } ); }); } function delay(ms) { return new Promise(res => setTimeout(res, ms)); } async function saveXlsx(results, outPath) { const wb = new ExcelJS.Workbook(); await wb.xlsx.readFile(outPath); const ws = wb.getWorksheet('账号数据'); results.forEach((row, i) => { const rowNum = i + 2; const values = Object.values(row); values.forEach((val, j) => { const cell = ws.getCell(rowNum, j + 1); if (/^\d+$/.test(String(val))) { cell.value = Number(val); } else { cell.value = String(val); } }); }); await wb.xlsx.writeFile(outPath); console.log(`\n已保存到 ${outPath},共 ${results.length} 条`); } async function main() { const results = []; for (const account of accounts) { const row = await queryOne(account); if (row) results.push(row); await delay(500); } if (results.length === 0) { console.log('没有有效数据'); return; } const outPath = path.resolve(__dirname, './config/output.xlsx'); await saveXlsx(results, outPath); } main();