如何用Puppeteer JS从investing.com下载正常CSV格式历史数据?
解决Puppeteer下载Investing.com CSV文件出现.crdownload后缀的问题
.crdownload是Chrome浏览器未完成下载时的临时文件后缀,问题根源是你点击下载按钮后立刻关闭了浏览器,导致下载还没完成就被中断。要获取完整的CSV文件,必须等待下载完全结束后再关闭浏览器,以下是具体解决方案:
核心修改思路
- 监听下载事件获取目标文件名
- 循环检查文件状态,确认下载完成后再关闭浏览器
- 确保下载目录存在,避免路径错误
修改后的完整代码
//collector.mjs import puppeteer from "puppeteer"; import path from "path"; import fs from "fs/promises"; import { setTimeout } from 'timers/promises'; (async ()=>{ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setUserAgent('Chrome/105.0.0.0'); await page.goto("https://www.investing.com/equities/tesla-motors-historical-data", { waitUntil: "networkidle2", }); const downloadPath = path.resolve("./csvData"); // 提前创建下载目录(如果不存在) await fs.mkdir(downloadPath, { recursive: true }); const client = await page.target().createCDPSession(); await client.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: downloadPath, }); // 监听下载初始化事件,拿到服务器返回的文件名 let downloadedFileName; client.on('Page.downloadWillBegin', (event) => { downloadedFileName = event.suggestedFilename; }); // 触发下载 await page.evaluate(()=>{ document.querySelector("span[class='download-data_text__Myrn3']").click(); }); // 等待下载完成:循环检查文件是否存在且大小稳定 if (downloadedFileName) { const fullFilePath = path.join(downloadPath, downloadedFileName); let lastFileSize = -1; while (true) { try { const stats = await fs.stat(fullFilePath); // 等待1秒后再检查一次,确认文件大小不再变化 await setTimeout(1000); const newStats = await fs.stat(fullFilePath); if (stats.size === newStats.size && stats.size !== lastFileSize) { lastFileSize = stats.size; // 连续两次大小一致,判定下载完成 break; } } catch (err) { // 文件还未生成,继续等待 await setTimeout(500); } } } // 确认下载完成后再关闭浏览器 await browser.close(); })();
关键细节说明
- 监听下载事件:通过
Page.downloadWillBegin事件可以准确获取服务器返回的文件名,避免手动拼接文件名出错 - 文件状态检查:通过对比两次间隔1秒的文件大小,确保下载完全结束(单纯检查文件存在可能会误判为完成,因为.crdownload文件也会存在)
- 目录预创建:用
fs.mkdir的recursive: true参数确保下载目录存在,防止因目录不存在导致下载失败
内容的提问来源于stack exchange,提问作者marcius.tan
相关产品推荐
相关产品推荐

