Google Yahoo Finance 的 Sheets Scraping Options Chain,结果不完整
Google Sheets Scraping Options Chain from Yahoo Finance, Incomplete Results
我正在尝试从 Google 表格中的 Yahoo Finance 抓取期权定价数据。虽然我能够很好地拉动期权链,即
=IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2)
我发现它返回的结果与 Yahoo Finance 上的实际显示不完全匹配。具体来说,抓取的结果是不完整的——他们缺少一些罢工。即图表的前 5 行可能匹配,但随后它将开始仅返回每隔一次罢工(也就是跳过每隔一次罢工)。
为什么 IMPORTHTML 会返回与页面上实际显示的内容不匹配的“缩写”结果?更重要的是,是否有某种方法可以抓取 完整 数据(即不会跳过可用罢工的某些部分)?
我相信你的目标如下。
- 您想从
https://finance.yahoo.com/quote/TCOM/options?date=1610668800
的 URL 中检索完整的 table,并想将其放入 Spreadsheet。
问题和解决方法:
我可以复制你的问题。当我看到 HTML 数据时,不幸的是,我找不到 HTML 显示行和不显示行之间的区别。而且,我可以确认完整的 table 包含在 HTML 数据中。顺便说一句,当我使用 =IMPORTXML(A1,"//section[2]//tr")
对其进行测试时,会出现与 IMPORTHTML
相同的结果。所以我认为在这种情况下,IMPORTHTML
和IMPORTXML
可能无法检索到完整的table。
因此,在这个答案中,作为一种解决方法,我想建议使用 Sheets API 解析完整的 table。在这种情况下,使用 Google Apps 脚本。通过这个,我可以确认可以通过用 Sheet API.
解析 HTML table 来检索完整的 table
示例脚本:
请将以下脚本复制并粘贴到Spreadsheet和please enable Sheets API at Advanced Google services的脚本编辑器中。并且,请在脚本编辑器中运行 myFunction
的功能。这样,检索到的 table 被放入 sheetName
.
的 sheet
function myFunction() {
// Please set the following variables.
const url ="https://finance.yahoo.com/quote/TCOM/options?date=1610668800";
const sheetName = "Sheet1"; // Please set the destination sheet name.
const sessionNumber = 2; // Please set the number of session. In this case, the table of 2nd session is retrieved.
const html = UrlFetchApp.fetch(url).getContentText();
const section = [...html.matchAll(/<section[\s\S\w]+?<\/section>/g)];
if (section.length >= sessionNumber) {
if (section[sessionNumber].length == 1) {
const table = section[sessionNumber][0].match(/<table[\s\S\w]+?<\/table>/);
if (table) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const body = {requests: [{pasteData: {html: true, data: table[0], coordinate: {sheetId: ss.getSheetByName(sheetName).getSheetId()}}}]};
Sheets.Spreadsheets.batchUpdate(body, ss.getId());
}
} else {
throw new Error("No table.");
}
} else {
throw new Error("No table.");
}
}
const sessionNumber = 2;
表示 =IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2)
的 2
。
参考文献:
这里有一个更简单的方法来获取给定期权的最后市场价格。为您添加此功能 Google Sheets 脚本编辑器。
function OPTION(ticker) {
var ticker = ticker+"";
var URL = "finance.yahoo.com/quote/"+ticker;
var html = UrlFetchApp.fetch(URL).getContentText();
var count = (html.match(/regularMarketPrice/g) || []).length;
var query = "regularMarketPrice";
var loc = 0;
var n = parseInt(count)-2;
for(i = 0; i<n; i++) {
loc = html.indexOf(query,loc+1);
}
var value = html.substring(loc+query.length+9, html.indexOf(",", loc+query.length+9));
return value*100;
}
在您的 google 工作表中输入 Yahoo Finance 选项代码,如下所示
=OPTION("AAPL210430C00060000")
在雅虎金融中,所有数据都可以在一个名为 root.App.main 的大 json 中使用。所以要得到完整的数据集,进行如下操作
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
然后您可以选择获取您需要的信息。复制此示例 https://docs.google.com/spreadsheets/d/1sTA71PhpxI_QdGKXVAtb0Rc3cmvPLgzvXKXXTmiec7k/copy
编辑
如果您想获得可用数据的完整列表,您可以通过这个简单的脚本检索它
// mike.steelson
let result = [];
function getAllDataJSON(url = 'https://finance.yahoo.com/quote/TCOM/options?date=1610668800') {
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
getAllData(eval(data),'data')
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
sh.getRange(1, 1, result.length, result[0].length).setValues(result);
}
function getAllData(obj,id) {
const regex = new RegExp('[^0-9]+');
for (let p in obj) {
var newid = (regex.test(p)) ? id + '["' + p + '"]' : id + '[' + p + ']';
if (obj[p]!=null){
if (typeof obj[p] != 'object' && typeof obj[p] != 'function'){
result.push([newid, obj[p]]);
}
if (typeof obj[p] == 'object') {
getAllData(obj[p], newid );
}
}
}
}
我正在尝试从 Google 表格中的 Yahoo Finance 抓取期权定价数据。虽然我能够很好地拉动期权链,即
=IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2)
我发现它返回的结果与 Yahoo Finance 上的实际显示不完全匹配。具体来说,抓取的结果是不完整的——他们缺少一些罢工。即图表的前 5 行可能匹配,但随后它将开始仅返回每隔一次罢工(也就是跳过每隔一次罢工)。
为什么 IMPORTHTML 会返回与页面上实际显示的内容不匹配的“缩写”结果?更重要的是,是否有某种方法可以抓取 完整 数据(即不会跳过可用罢工的某些部分)?
我相信你的目标如下。
- 您想从
https://finance.yahoo.com/quote/TCOM/options?date=1610668800
的 URL 中检索完整的 table,并想将其放入 Spreadsheet。
问题和解决方法:
我可以复制你的问题。当我看到 HTML 数据时,不幸的是,我找不到 HTML 显示行和不显示行之间的区别。而且,我可以确认完整的 table 包含在 HTML 数据中。顺便说一句,当我使用 =IMPORTXML(A1,"//section[2]//tr")
对其进行测试时,会出现与 IMPORTHTML
相同的结果。所以我认为在这种情况下,IMPORTHTML
和IMPORTXML
可能无法检索到完整的table。
因此,在这个答案中,作为一种解决方法,我想建议使用 Sheets API 解析完整的 table。在这种情况下,使用 Google Apps 脚本。通过这个,我可以确认可以通过用 Sheet API.
解析 HTML table 来检索完整的 table示例脚本:
请将以下脚本复制并粘贴到Spreadsheet和please enable Sheets API at Advanced Google services的脚本编辑器中。并且,请在脚本编辑器中运行 myFunction
的功能。这样,检索到的 table 被放入 sheetName
.
function myFunction() {
// Please set the following variables.
const url ="https://finance.yahoo.com/quote/TCOM/options?date=1610668800";
const sheetName = "Sheet1"; // Please set the destination sheet name.
const sessionNumber = 2; // Please set the number of session. In this case, the table of 2nd session is retrieved.
const html = UrlFetchApp.fetch(url).getContentText();
const section = [...html.matchAll(/<section[\s\S\w]+?<\/section>/g)];
if (section.length >= sessionNumber) {
if (section[sessionNumber].length == 1) {
const table = section[sessionNumber][0].match(/<table[\s\S\w]+?<\/table>/);
if (table) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const body = {requests: [{pasteData: {html: true, data: table[0], coordinate: {sheetId: ss.getSheetByName(sheetName).getSheetId()}}}]};
Sheets.Spreadsheets.batchUpdate(body, ss.getId());
}
} else {
throw new Error("No table.");
}
} else {
throw new Error("No table.");
}
}
const sessionNumber = 2;
表示=IMPORTHTML("https://finance.yahoo.com/quote/TCOM/options?date=1610668800","table",2)
的2
。
参考文献:
这里有一个更简单的方法来获取给定期权的最后市场价格。为您添加此功能 Google Sheets 脚本编辑器。
function OPTION(ticker) {
var ticker = ticker+"";
var URL = "finance.yahoo.com/quote/"+ticker;
var html = UrlFetchApp.fetch(URL).getContentText();
var count = (html.match(/regularMarketPrice/g) || []).length;
var query = "regularMarketPrice";
var loc = 0;
var n = parseInt(count)-2;
for(i = 0; i<n; i++) {
loc = html.indexOf(query,loc+1);
}
var value = html.substring(loc+query.length+9, html.indexOf(",", loc+query.length+9));
return value*100;
}
在您的 google 工作表中输入 Yahoo Finance 选项代码,如下所示
=OPTION("AAPL210430C00060000")
在雅虎金融中,所有数据都可以在一个名为 root.App.main 的大 json 中使用。所以要得到完整的数据集,进行如下操作
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
然后您可以选择获取您需要的信息。复制此示例 https://docs.google.com/spreadsheets/d/1sTA71PhpxI_QdGKXVAtb0Rc3cmvPLgzvXKXXTmiec7k/copy
编辑
如果您想获得可用数据的完整列表,您可以通过这个简单的脚本检索它
// mike.steelson
let result = [];
function getAllDataJSON(url = 'https://finance.yahoo.com/quote/TCOM/options?date=1610668800') {
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
getAllData(eval(data),'data')
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
sh.getRange(1, 1, result.length, result[0].length).setValues(result);
}
function getAllData(obj,id) {
const regex = new RegExp('[^0-9]+');
for (let p in obj) {
var newid = (regex.test(p)) ? id + '["' + p + '"]' : id + '[' + p + ']';
if (obj[p]!=null){
if (typeof obj[p] != 'object' && typeof obj[p] != 'function'){
result.push([newid, obj[p]]);
}
if (typeof obj[p] == 'object') {
getAllData(obj[p], newid );
}
}
}
}