Node.js读取CSV的Account ID调用API合并数据生成新CSV求助
Node.js CSV与API数据合并实现方案
前置依赖
需安装第三方CSV处理工具,Node.js 18+ 可使用原生fetch无需额外安装请求库:
npm install csv-parser csv-writer
完整实现代码
const fs = require('fs'); const csv = require('csv-parser'); const createCsvWriter = require('csv-writer').createObjectCsvWriter; // 配置项 const INPUT_CSV_PATH = './input.csv'; const OUTPUT_CSV_PATH = './output.csv'; const API_BASE = 'https://company.callout.io/v1/accounts/'; const CONCURRENT_LIMIT = 5; // 并发请求数,避免触发API限流 // 并发控制工具函数 const limitConcurrency = (limit, tasks) => { const executing = new Set(); return Promise.all(tasks.map(task => { while (executing.size >= limit) { return Promise.race(executing).then(() => limitConcurrency(limit, [task])); } const promise = Promise.resolve().then(task); executing.add(promise); promise.finally(() => executing.delete(promise)); return promise; })); }; (async () => { // 1. 读取CSV并自动识别表头 const rows = []; let headers = []; await new Promise((resolve, reject) => { fs.createReadStream(INPUT_CSV_PATH) .pipe(csv()) .on('headers', (headerList) => { headers = headerList; }) .on('data', (row) => rows.push(row)) .on('end', resolve) .on('error', reject); }); // 2. 自动识别Account ID列,无需硬编码列名 const accountIdKey = headers.find(h => h.toLowerCase().replace(/\s/g, '').includes('accountid') ); if (!accountIdKey) throw new Error('未在CSV中找到Account ID列'); // 3. 批量请求API合并数据 await limitConcurrency(CONCURRENT_LIMIT, rows.map(row => async () => { const accountId = row[accountIdKey]?.toString().trim(); // 兼容空Account ID、无效ID的情况 if (!accountId) { row.Status = ''; row['Status Set On'] = ''; return; } try { const res = await fetch(`${API_BASE}${encodeURIComponent(accountId)}`); if (!res.ok) throw new Error('API请求失败'); const apiData = await res.json(); row.Status = apiData.status || ''; row['Status Set On'] = apiData.created_on || ''; } catch (e) { // API请求失败时留空,不中断整体流程 row.Status = ''; row['Status Set On'] = ''; } })); // 4. 输出新CSV,动态生成表头不硬编码原有列 const csvWriter = createCsvWriter({ path: OUTPUT_CSV_PATH, header: [ ...headers.map(h => ({id: h, title: h})), {id: 'Status', title: 'Status'}, {id: 'Status Set On', title: 'Status Set On'} ] }); await csvWriter.writeRecords(rows); console.log('CSV生成完成'); })();
关键兼容逻辑说明
- 列名适配:自动识别含
account+id关键字的列作为账号列,忽略大小写、空格差异,无需硬编码原有CSV列名 - 异常兼容:
- 空账号、负账号、特殊字符账号自动处理,空值直接跳过API请求
- API请求超时、返回错误、字段缺失时新增列自动填充空值,不会中断整体导出流程
- 异步问题修复:等待所有CSV读取完成、所有API请求返回后再写入文件,避免异步导致的空值、
[object Object]异常 - 并发控制:可自行调整并发请求数,避免触发第三方API限流规则
内容的提问来源于stack exchange,提问作者apex2022
相关产品推荐
相关产品推荐

