如何在 Google Apps 脚本中使用 Cheerio 提取 HTML 表格数据(雅虎财经)?

Posted

技术标签:

【中文标题】如何在 Google Apps 脚本中使用 Cheerio 提取 HTML 表格数据(雅虎财经)?【英文标题】:How to pull HTML table data (Yahoo Finance) with Cheerio in Google Apps Script? 【发布时间】:2021-11-30 11:17:09 【问题描述】:

我正在尝试从https://finance.yahoo.com/quote/CL%3DF/history?p=CL%3DF 获取整个表格数据。在浏览器上,网页默认显示截至 2020 年 10 月 12 日的 1 年数据。但是以下代码由于某种原因没有提取整个表数据。它只提取了部分数据,仅提取了不到 5 个月的数据,直到 2021 年 5 月 20 日。我错过了什么?任何人都可以帮助修复代码中的任何错误吗?谢谢!

function test() 
  const url = 'https://finance.yahoo.com/quote/CL%3DF/history?p=CL%3DF';
  const res = UrlFetchApp.fetch(url,  muteHttpExceptions: true ).getContentText();
  const $ = Cheerio.load(res);
  // The URL webpage shows one year data down to Oct 12, 2021 on the browser.
  // But the code below got data only down to May 20, 2020.  Why am I mssing?
  var data = $('table').find('td').toArray().map(x => $(x).text());
  console.log(data[data.length-8]);     // Print the last row date other than the web note

【问题讨论】:

【参考方案1】:

当我看到 html 数据时,表格选项卡似乎没有所有数据。但幸运的是,我注意到 javascript 中的对象包含您期望的所有数据。那么下面修改后的脚本呢?

修改脚本:

在此修改后的脚本中,使用了电子表格的容器绑定脚本。当然,您可以使用独立类型。但是这种情况,请修改SpreadsheetApp.getActiveSpreadsheet()

当您使用该脚本时,请将以下修改后的脚本复制粘贴到Spreadsheet的脚本编辑器中并设置工作表名称,然后运行。这样,所有数据都被检索并放入电子表格。

function test() 
  const url = 'https://finance.yahoo.com/quote/CL%3DF/history?p=CL%3DF';
  const res = UrlFetchApp.fetch(url,  muteHttpExceptions: true ).getContentText();
  const $ = Cheerio.load(res);

  // I modified below script
  const data = $('script').toArray().reduce((ar, x) => 
    const c = $(x).get()[0].children;
    if (c.length > 0) 
      const d = c[0].data.trim().match(/("context"[\s\S\w]+);\n\(this\)\);/);
      if (d && d.length == 2) 
        ar.push(JSON.parse(d[1]));
      
    
    return ar;
  , []);
  if (data.length == 0) throw new Error("No data.");
  const header = ["date","open","high","low","close","adjclose","volume"];
  const ar = data[0].context.dispatcher.stores.HistoricalPriceStore.prices.map(o => header.map(h => h == "date" ? new Date(o[h] * 1000) : (o[h] || "")));
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); // <--- Please set the sheet name you want to put the values.
  sheet.getRange(1, 1, ar.length, ar[0].length).setValues(ar);

结果:

上面的脚本运行时,得到如下结果。

参考资料:

reduce() map()

【讨论】:

抱歉!有用!非常感谢! @Newbie 感谢您的回复。我很高兴你的问题得到了解决。也谢谢你。

以上是关于如何在 Google Apps 脚本中使用 Cheerio 提取 HTML 表格数据(雅虎财经)?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Apps 脚本在 Google 表格中“清除格式”

如何使用 Google Apps 脚本将公式添加到 Google 表格?

如何在 Google Apps 脚本中为 DateTimePicker 获取正确的 DateTime?

如何从 Google 电子表格中的 Google Apps 脚本自动更新“站点地图”功能?

如何在 Google Apps 脚本中使用 Cheerio 提取 HTML 表格数据?

在 Google Apps 脚本中使用 Mandrill API