如何通过Javascript配合Apify、Puppeteer从Google Trends下载CSV
问题根因
你现有代码的核心错误如下:
- 未做URL特征匹配就直接拦截第一个XHR请求,大概率拦截到的不是CSV下载接口,自然返回内容不对
- 请求拦截逻辑注册时机晚于点击下载按钮的操作,可能错过CSV下载请求
- 重复读写本地文件增加了出错概率,无需先存本地再读取
- 手动拼接Cookie逻辑可能遗漏谷歌校验必要的属性,导致接口返回异常
可行修复方案
直接监听页面的响应事件,匹配CSV下载接口的特征直接拿返回内容,不需要手动拦截重发请求,修复后代码如下:
const path = require('path'); const downloadPath1 = path.resolve(__dirname, './downloads'); const fs = require('fs'); const { promisify } = require('util'); const mkdirAsync = promisify(fs.mkdir); try { // 加recursive避免嵌套目录不存在报错 await mkdirAsync(downloadPath1, { recursive: true }); } catch (e) {} // 先注册响应监听,再点击下载按钮 const csvPromise = new Promise((resolve, reject) => { page.on('response', async (response) => { const reqUrl = response.url(); // 匹配Google Trends CSV下载接口的特征,可根据实际请求调整关键词 if (reqUrl.includes('export') && reqUrl.includes('csv') && response.status() === 200) { try { const csvContent = await response.buffer(); resolve(csvContent); } catch (err) { reject(err); } } }); }); // 点击下载按钮 await page.waitForSelector(csvSelector, { timeout: 15000 }); await page.click(csvSelector); // 等待获取CSV内容 const csvBuffer = await csvPromise; // 本地存储+存入Apify键值对,不需要额外读目录 fs.writeFileSync(path.join(downloadPath1, 'google_trends.csv'), csvBuffer); await Apify.setValue('MY-Csv.csv', csvBuffer, { contentType: 'text/csv; charset=utf-8' });
额外注意事项
- 如果你需要的是多维度的完整趋势数据,可以先模拟页面上切换完所有需要的维度(比如时间范围、地区、对比关键词)再点击导出按钮
- 部分场景下CSV导出接口返回的是gzip压缩内容,上述代码用buffer接收可以自动兼容,不需要额外处理编码
内容的提问来源于stack exchange,提问作者zaher mech
相关产品推荐
相关产品推荐

