Puppeteer+Express API数据不更新问题求助
解决Puppeteer爬取股票数据API实时更新问题
核心问题分析
你遇到的问题本质是API数据未与爬取结果实时同步,nodemon重启时文件更新但接口返回空数组,大概率是文件读取缓存、写入不完整或内存数据未及时更新导致的。
具体解决方案
1. 实时读取文件,避免缓存
如果使用Express等框架,不要在启动时一次性将data.json读入内存,而是每次请求/data接口时重新读取文件:
// Express 示例(回调版) const fs = require('fs'); const express = require('express'); const app = express(); app.get('/data', (req, res) => { fs.readFile('./data.json', 'utf8', (err, rawData) => { if (err) { console.error(err); return res.status(500).send('读取数据失败'); } try { const data = JSON.parse(rawData); res.json(data); } catch (parseErr) { console.error(parseErr); res.status(500).send('数据格式错误'); } }); });
或者用异步Promise版本:
// Express 示例(async/await版) app.get('/data', async (req, res) => { try { const rawData = await fs.promises.readFile('./data.json', 'utf8'); const data = JSON.parse(rawData); res.json(data); } catch (err) { console.error(err); res.status(500).send('读取数据失败'); } });
2. 增量更新数据,减少IO操作
不要每次爬取都覆盖整个data.json,对比新旧数据只更新变动项:
function updateChangedData(oldData, newData) { return oldData.map(oldItem => { const newItem = newData.find(item => item.code === oldItem.code); // 只更新价格、涨跌幅等有变化的字段 if (newItem && (newItem.price !== oldItem.price || newItem.change !== oldItem.change)) { return { ...oldItem, ...newItem }; } return oldItem; }); } // 爬取逻辑中调用 const oldData = JSON.parse(fs.readFileSync('./data.json', 'utf8')); const newStockData = await /* 你的Puppeteer爬取逻辑 */; const updatedData = updateChangedData(oldData, newStockData); // 仅当数据变化时写入文件 if (JSON.stringify(updatedData) !== JSON.stringify(oldData)) { fs.writeFileSync('./data.json', JSON.stringify(updatedData, null, 2)); }
3. 原子写入文件,避免读取空内容
nodemon重启时可能出现文件未写完就被读取的情况,改用原子写入(先写临时文件,再替换原文件):
const tempFilePath = './data.tmp.json'; // 先写入临时文件 await fs.promises.writeFile(tempFilePath, JSON.stringify(updatedData, null, 2)); // 替换原文件,保证原子性 await fs.promises.rename(tempFilePath, './data.json');
4. 改用内存存储数据(最优方案)
每秒更新场景下文件IO是瓶颈,直接将数据存在内存中,API直接返回内存数据:
// 全局变量存储实时股票数据 let realtimeStockData = []; // Puppeteer定时爬取函数 async function crawlAndUpdateData() { const newData = await /* 你的Puppeteer爬取逻辑 */; // 增量更新内存数据 realtimeStockData = updateChangedData(realtimeStockData, newData); } // API接口直接返回内存数据 app.get('/data', (req, res) => { res.json(realtimeStockData); }); // 每秒执行一次爬取更新 setInterval(crawlAndUpdateData, 1000);
内容的提问来源于stack exchange,提问作者Apurv JHA
相关产品推荐
相关产品推荐

