Home > OS >  How to pull Yahoo Finance Historical Price Data from its Object with Google Apps Script?
How to pull Yahoo Finance Historical Price Data from its Object with Google Apps Script?

Time:12-21

@Tanaike made this beautiful codes for Google Apps Script a year ago as posted enter image description here

Note:

  • If you want to directly load crypto-js, you can also use the following script. 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=F/history?p=CL=F';
  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). 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. Please be careful about this.

Reference:

  • Related