如何在 Google Apps 脚本中使用 Cheerio 提取 HTML table 数据 (Yahoo Finance)?
How to pull HTML table data (Yahoo Finance) with Cheerio in Google Apps Script?
我正在尝试从 https://finance.yahoo.com/quote/CL%3DF/history?p=CL%3DF 获取整个 table 数据。在浏览器上,该网页默认显示截至 2020 年 10 月 12 日的 1 年数据。但是由于某些原因,下面的代码没有提取整个 table 数据。它只提取了部分数据,不到 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
}
当我看到HTML数据时,似乎table标签没有所有数据。但幸运的是,我注意到 Javascript 中的对象具有您期望的所有数据。那么下面的修改脚本怎么样?
修改后的脚本:
在这个修改后的脚本中,使用了Spreadsheet的容器绑定脚本。当然,您可以使用独立类型。但那样的话,请修改SpreadsheetApp.getActiveSpreadsheet()
.
当您使用此脚本时,请将以下修改后的脚本复制并粘贴到Spreadsheet的脚本编辑器中,并设置sheet名称和运行。通过这种方式,所有数据都被检索并放入 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);
}
结果:
当上述脚本为运行时,得到如下结果
参考文献:
我正在尝试从 https://finance.yahoo.com/quote/CL%3DF/history?p=CL%3DF 获取整个 table 数据。在浏览器上,该网页默认显示截至 2020 年 10 月 12 日的 1 年数据。但是由于某些原因,下面的代码没有提取整个 table 数据。它只提取了部分数据,不到 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
}
当我看到HTML数据时,似乎table标签没有所有数据。但幸运的是,我注意到 Javascript 中的对象具有您期望的所有数据。那么下面的修改脚本怎么样?
修改后的脚本:
在这个修改后的脚本中,使用了Spreadsheet的容器绑定脚本。当然,您可以使用独立类型。但那样的话,请修改SpreadsheetApp.getActiveSpreadsheet()
.
当您使用此脚本时,请将以下修改后的脚本复制并粘贴到Spreadsheet的脚本编辑器中,并设置sheet名称和运行。通过这种方式,所有数据都被检索并放入 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);
}
结果:
当上述脚本为运行时,得到如下结果