import axios from 'axios'; import { fileURLToPath } from 'url'; async function fetch(startDate = null, endDate = null, retryCount = 3) { try { const currentDate = new Date(); if (!startDate) { startDate = new Date(currentDate); startDate.setDate(startDate.getDate() - 30); startDate = startDate.toISOString().split('T')[0]; } if (!endDate) { endDate = currentDate.toISOString().split('T')[0]; } console.log('正在获取沪深300指数数据...'); console.log(`时间范围: ${startDate} 至 ${endDate}`); console.log(`数据源: 腾讯财经API`); // 沪深300指数代码 const symbol = '000300'; // 使用腾讯财经的API端点获取历史数据 const response = await axios.get('https://web.ifzq.gtimg.cn/appstock/app/kline/kline?param=sh' + symbol + ',day,' + startDate + ',' + endDate + ',640', { headers: { 'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' }, timeout: 10000 // 设置10秒超时 }); console.log(`\nAPI状态: ${response.status}`); const data = response.data; console.log(`响应数据:`, JSON.stringify(data, null, 2)); const allData = []; if (data && data.data && data.data['sh' + symbol] && data.data['sh' + symbol].day) { const klineData = data.data['sh' + symbol].day; console.log(`数据条数: ${klineData.length}`); for (const item of klineData) { allData.push({ date: item[0], open: parseFloat(item[1]), close: parseFloat(item[2]), high: parseFloat(item[3]), low: parseFloat(item[4]), volume: parseFloat(item[5]), amount: 0, // 腾讯财经API没有返回成交额数据,设置为0 source: '腾讯财经API', fetchTime: new Date().toISOString() }); } } else { console.log('数据条数: 0'); } allData.sort((a, b) => a.date.localeCompare(b.date)); console.log(`\n共获取到 ${allData.length} 条沪深300指数数据`); return { symbol: 'sh000300', name: '沪深300指数', startDate, endDate, count: allData.length, data: allData, fetchTime: new Date().toISOString(), note: '数据来源: 腾讯财经API' }; } catch (error) { console.error('获取沪深300指数数据失败:', error.message); if (error.response) { console.error(`HTTP状态码: ${error.response.status}`); console.error(`响应数据:`, error.response.data); } // 重试机制 if (retryCount > 0) { console.log(`正在重试... (剩余重试次数: ${retryCount - 1})`); // 等待1秒后重试 await new Promise(resolve => setTimeout(resolve, 1000)); return fetch(startDate, endDate, retryCount - 1); } throw error; } } export { fetch }; const isMainModule = () => { const currentFile = fileURLToPath(import.meta.url); const mainFile = process.argv[1]; return currentFile === mainFile; }; function parseCommandLineArgs() { const args = process.argv.slice(2); let startDate = null; let endDate = null; for (let i = 0; i < args.length; i++) { if (args[i] === '--start' && i + 1 < args.length) { startDate = args[i + 1]; i++; } else if (args[i] === '--end' && i + 1 < args.length) { endDate = args[i + 1]; i++; } else if (args[i] === '--help') { console.log('使用方法:'); console.log(' bun sh300.fetcher.js [选项]'); console.log(''); console.log('选项:'); console.log(' --start YYYY-MM-DD 指定开始日期(默认:30天前)'); console.log(' --end YYYY-MM-DD 指定结束日期(默认:今天)'); console.log(' --help 显示帮助信息'); console.log(''); console.log('示例:'); console.log(' bun sh300.fetcher.js'); console.log(' bun sh300.fetcher.js --start 2024-01-01 --end 2024-01-31'); process.exit(0); } } return { startDate, endDate }; } if (isMainModule()) { const { startDate, endDate } = parseCommandLineArgs(); console.log('='.repeat(50)); console.log('沪深300指数数据获取脚本'); console.log('='.repeat(50)); fetch(startDate, endDate) .then(result => { console.log('\n' + '='.repeat(50)); console.log('获取结果:'); console.log(` 指数代码: ${result.symbol}`); console.log(` 指数名称: ${result.name}`); console.log(` 开始日期: ${result.startDate}`); console.log(` 结束日期: ${result.endDate}`); console.log(` 数据条数: ${result.count}`); console.log(` 获取时间: ${result.fetchTime}`); console.log(` 提示: ${result.note}`); if (result.count > 0) { console.log('-'.repeat(50)); console.log('指数数据:'); result.data.forEach(item => { console.log(` ${item.date} 开盘: ${item.open} 最高: ${item.high} 最低: ${item.low} 收盘: ${item.close}`); }); } console.log('='.repeat(50)); }) .catch(error => { console.error('执行失败:', error); process.exit(1); }); }