简体   繁体   English

如何使用 Google Apps 脚本从其对象中提取 Yahoo Finance 历史价格数据?

[英]How to pull Yahoo Finance Historical Price Data from its Object with Google Apps Script?

@Tanaike made this beautiful codes for Google Apps Script a year ago as posted here . @Tanaike 一年前为 Google Apps Script 制作了这个漂亮的代码,发布在这里 It worked very well up until recently.直到最近它运作良好。 Because of some changes in the Yahoo Finance webpage, it doesn't pull the historical price table data since this week(12/20/21).由于雅虎财经网页发生了一些变化,自本周(12/20/21)以来,它不再拉取历史价格表数据。 Now I get an error message, "TypeError: Cannot read properies of undefined(reading 'prices'):".现在我收到一条错误消息,“TypeError:无法读取未定义的属性(读取‘价格’):”。 Can anyone help me out what changes should be made in the codes?任何人都可以帮我解决代码中应该做哪些更改吗? Thank you for any help!感谢您的任何帮助!

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);
}

When I saw the HTML from the URL again, I noticed that your expected values are converted to the salted base64 data.当我再次看到来自 URL 的 HTML 时,我注意到您的预期值已转换为加盐的 base64 数据。 In this case, unfortunately, only the built-in functions of Google Apps Script cannot decode it.在这种情况下,不幸的是,只有 Google Apps Script 的内置函数无法对其进行解码。 So, in this answer, I use crypto-js.所以,在这个答案中,我使用了 crypto-js。 Ref Fortunately, in the current stage, crypto-js can be used with Google Apps Script. Ref幸运的是,在当前阶段,crypto-js 可以与 Google Apps Script 一起使用。 So, please do the following flow.因此,请执行以下流程。

Usage:用法:

1. Get crypto-js. 1.获取crypto-js。

Please access https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js .请访问https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js And, copy and paste the script to the script editor of Google Apps Script, and save the script.然后,将脚本复制并粘贴到 Google Apps Script 的脚本编辑器中,并保存脚本。

2. Modify script. 2.修改脚本。

Please modify your script as follows.请按如下方式修改您的脚本。 When I saw the HTML, I noticed that the data is converted by the salted base64.当我看到 HTML 时,我注意到数据是由加盐的 base64 转换的。 In order to decrypt the data, it is required to use the key data.为了解密数据,需要使用密钥数据。 But, unfortunately, I couldn't find the key data from the HTML.但是,不幸的是,我无法从 HTML 中找到关键数据。 When I searched for it, I found this thread .当我搜索它时,我找到了这个线程 From the thread, I could retrieve the key data.从线程中,我可以检索关键数据。 By this, I could modify the script as follows and could achieve your goal.这样,我可以按如下方式修改脚本并可以实现您的目标。

When this script is run, the salted base64 data is decrypted with crypto-js , and the values are retrieved.运行此脚本时,加盐的 base64 数据将使用crypto-js解密,并检索值。

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);

  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"];

  // --- I modified the below script.
  const obj1 = data[0];
  const { _cs, _cr } = obj1;
  if (!_cs || !_cr) return;
  const key = CryptoJS.algo.PBKDF2.create({ keySize: 8 }).compute(_cs, JSON.parse(_cr)).toString();
  const obj2 = JSON.parse(CryptoJS.enc.Utf8.stringify(CryptoJS.AES.decrypt(obj1.context.dispatcher.stores, key)));
  const ar = obj2.HistoricalPriceStore.prices.map(o => header.map(h => h == "date" ? new Date(o[h] * 1000) : (o[h] || "")));
  // ---

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
  sheet.getRange(1, 1, ar.length, ar[0].length).setValues(ar);
}

Testing:测试:

When this script is run, the following result is obtained.运行此脚本时,将获得以下结果。

在此处输入图像描述

Note:笔记:

  • If you want to directly load crypto-js , you can also use the following script.如果你想直接加载crypto-js ,你也可以使用下面的脚本。 But, in this case, the process cost becomes higher than that of the above flow.但是,在这种情况下,处理成本变得高于上述流程。

     const cdnjs = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"; eval(UrlFetchApp.fetch(cdnjs).getContentText());
  • The whole script using this is as follows.使用它的整个脚本如下。

 function test2() { 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); 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"]; // --- I modified the below script. const cdnjs = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"; eval(UrlFetchApp.fetch(cdnjs).getContentText()); const obj1 = data[0]; const { _cs, _cr } = obj1; if (;_cs ||._cr) return. const key = CryptoJS.algo:PBKDF2.create({ keySize, 8 }).compute(_cs. JSON;parse(_cr)).toString(). const obj2 = JSON.parse(CryptoJS.enc.Utf8.stringify(CryptoJS.AES.decrypt(obj1.context,dispatcher;stores. key))). const ar = obj2.HistoricalPriceStore.prices?map(o => header:map(h => h == "date"; new Date(o[h] * 1000). (o[h] || ""))). // --- const sheet = SpreadsheetApp;getActiveSpreadsheet().getSheetByName("Sheet1"), sheet,getRange(1. 1, ar.length. ar[0];length).setValues(ar); }

IMPORTANT重要的

  • I can confirm that this method can be used for the current situation (December, 21, 2022).我可以确认这种方法可以用于当前情况(2022 年 12 月 21 日)。 But, when the specification in the data and HTML is changed in the future update on the server side, this script might not be able to be used.但是,当数据和 HTML 中的规范在服务器端的未来更新中发生变化时,此脚本可能无法使用。 Please be careful about this.请注意这一点。

Reference:参考:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在应用程序脚本中从 yahoo Finance API 返回历史价格数组 - Returning array of historical prices from yahoo finance API in apps script 如何在 Google Apps 脚本中从 Yahoo Finance XHR 的 Complex Object 获取值 - How to get Values from Yahoo Finance XHR's Complex Object in Google Apps Script 如何将 Yahoo Finance 中的历史数据导入 Google 表格并使其自动更新? - How to Import Historical Data from Yahoo Finance into Google Sheets and make it Auto-Update? 使用 Google Apps 脚本提取当前价格变化百分比(Google 财经) - Pulling current price change % (Google Finance) with Google Apps Script 如何使用 Apps Script 在 Google Sheets 中记录历史数据 - How to record historical data in Google Sheets using Apps Script 触发运行 Google Sheets 脚本以批量从 Yahoo Finance 获取 URL 数据 - Trigger-run a Google Sheets script to fetch URL data from Yahoo Finance in batches 我如何使用谷歌应用程序脚本来修改我从谷歌分析中提取的数据? - How do i use google apps script to modify data that i pull from google analytics? 如何使用Apps Script Execution API从Google表格中提取数据 - How to use Apps Script Execution API to pull data from a Google Sheet 如何通过使用 arrays 从 Google 表格中提取数据并格式化来优化 Apps 脚本代码? - How to optimise Apps Script code by using arrays to pull data from Google Sheets and format it? Google Apps脚本:如何从一个电子表格中提取今天输入的数据并将其转换为另一电子表格? - Google Apps Script: How do I pull data entered today from one spreadsheet and transpose it to another?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM