使用 App-Script 从网站 HTML table 获取数据并传输到 Google 表格
Grab data from website HTML table and transfer to Google Sheets using App-Script
好的,我知道有类似的问题,但到目前为止我还没有找到适合我的答案。我想做的是从网络上的整个 HTML table (https://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html) 收集数据,然后将其 it/transfer 解析为我的 [=31= 中的一个范围] Sheet。下面的代码可能是迄今为止我发现的最接近的东西,因为至少它不会出错,但它只会找到一个字符串或值,而不是整个 table。我在他们使用 xmlservice.parse 的地方找到了其他答案,但这对我不起作用,我相信是因为 HTML 格式存在无法解析的问题。有没有人知道如何编辑我下面的内容,或者有可能适用于该网站的全新想法?
function SAMPLE() {
const url="http://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html#sgl-basic?"
// Get all the static HTML text of the website
const res = UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getContentText();
// Find the index of the string of the parameter we are searching for
index = res.search("td class");
// create a substring to only get the right number values ignoring all the HTML tags and classes
sub = res.substring(index+92,index+102);
Logger.log(sub);
return sub;
}
我知道我可以在 Google Sheet 中本地使用 importHTML,这就是我目前正在做的事情。然而,我正在为超过 350 个网页 table 执行此操作,并遍历每个网页以加载它,然后将值复制到另一个 sheet。当 App Script 反复等待 Sheet 加载 importHTML 然后获取一些数据并在另一个 url 上重新执行时,它会陷入相当多的困境。对于此 post 中的任何格式问题或我做错的事情,我深表歉意,这是我第一次 post 来到这里。
编辑: 好的,我找到了一个可行的方法,但它仍然比我想要的要慢得多,因为它使用 Drive API 创建一个包含 HTML 数据的文档,然后从那里解析并创建一个数组。 Drive.Files.Insert 行是最耗时的部分。任何人都知道如何使它更快?现在对你来说可能并不那么慢,但是当我需要这样做 350 次时,它就会加起来。
function parseTablesFromHTML() {
var html = UrlFetchApp.fetch("https://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html");
var docId = Drive.Files.insert(
{ title: "temporalDocument", mimeType: MimeType.GOOGLE_DOCS },
html.getBlob()
).id;
var tables = DocumentApp.openById(docId)
.getBody()
.getTables();
var res = tables.map(function(table) {
var values = [];
for (var row = 0; row < table.getNumRows(); row++) {
var temp = [];
var cols = table.getRow(row);
for (var col = 0; col < cols.getNumCells(); col++) {
temp.push(cols.getCell(col).getText());
}
values.push(temp);
}
return values;
});
Drive.Files.remove(docId);
var range=SpreadsheetApp.getActive().getSheetByName("Test").getRange(3,6,res[0].length,res[0][0].length);
range.setValues(res[0]);
SpreadsheetApp.flush();
}
公式求解
尝试
=importhtml(url,"table",1)
脚本的其他解决方案
function importTableHTML() {
var url = 'https://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html'
var html = '<table' + UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getContentText().replace(/(\r\n|\n|\r|\t| )/gm,"").match(/(?<=\<table).*(?=\<\/table)/g) + '</table>';
var trs = [...html.matchAll(/<tr[\s\S\w]+?<\/tr>/g)];
var data = [];
for (var i=0;i<trs.length;i++){
var tds = [...trs[i][0].matchAll(/<(td|th)[\s\S\w]+?<\/(td|th)>/g)];
var prov = [];
for (var j=0;j<tds.length;j++){
donnee=tds[j][0].match(/(?<=\>).*(?=\<\/)/g)[0];
prov.push(stripTags(donnee));
}
data.push(prov);
}
return(data);
}
function stripTags(body) {
var regex = /(<([^>]+)>)/ig;
return body.replace(regex,"");
}
好的,我知道有类似的问题,但到目前为止我还没有找到适合我的答案。我想做的是从网络上的整个 HTML table (https://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html) 收集数据,然后将其 it/transfer 解析为我的 [=31= 中的一个范围] Sheet。下面的代码可能是迄今为止我发现的最接近的东西,因为至少它不会出错,但它只会找到一个字符串或值,而不是整个 table。我在他们使用 xmlservice.parse 的地方找到了其他答案,但这对我不起作用,我相信是因为 HTML 格式存在无法解析的问题。有没有人知道如何编辑我下面的内容,或者有可能适用于该网站的全新想法?
function SAMPLE() {
const url="http://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html#sgl-basic?"
// Get all the static HTML text of the website
const res = UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getContentText();
// Find the index of the string of the parameter we are searching for
index = res.search("td class");
// create a substring to only get the right number values ignoring all the HTML tags and classes
sub = res.substring(index+92,index+102);
Logger.log(sub);
return sub;
}
我知道我可以在 Google Sheet 中本地使用 importHTML,这就是我目前正在做的事情。然而,我正在为超过 350 个网页 table 执行此操作,并遍历每个网页以加载它,然后将值复制到另一个 sheet。当 App Script 反复等待 Sheet 加载 importHTML 然后获取一些数据并在另一个 url 上重新执行时,它会陷入相当多的困境。对于此 post 中的任何格式问题或我做错的事情,我深表歉意,这是我第一次 post 来到这里。
编辑: 好的,我找到了一个可行的方法,但它仍然比我想要的要慢得多,因为它使用 Drive API 创建一个包含 HTML 数据的文档,然后从那里解析并创建一个数组。 Drive.Files.Insert 行是最耗时的部分。任何人都知道如何使它更快?现在对你来说可能并不那么慢,但是当我需要这样做 350 次时,它就会加起来。
function parseTablesFromHTML() {
var html = UrlFetchApp.fetch("https://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html");
var docId = Drive.Files.insert(
{ title: "temporalDocument", mimeType: MimeType.GOOGLE_DOCS },
html.getBlob()
).id;
var tables = DocumentApp.openById(docId)
.getBody()
.getTables();
var res = tables.map(function(table) {
var values = [];
for (var row = 0; row < table.getNumRows(); row++) {
var temp = [];
var cols = table.getRow(row);
for (var col = 0; col < cols.getNumCells(); col++) {
temp.push(cols.getCell(col).getText());
}
values.push(temp);
}
return values;
});
Drive.Files.remove(docId);
var range=SpreadsheetApp.getActive().getSheetByName("Test").getRange(3,6,res[0].length,res[0][0].length);
range.setValues(res[0]);
SpreadsheetApp.flush();
}
公式求解
尝试
=importhtml(url,"table",1)
脚本的其他解决方案
function importTableHTML() {
var url = 'https://www.sports-reference.com/cbb/schools/indiana/2022-gamelogs.html'
var html = '<table' + UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getContentText().replace(/(\r\n|\n|\r|\t| )/gm,"").match(/(?<=\<table).*(?=\<\/table)/g) + '</table>';
var trs = [...html.matchAll(/<tr[\s\S\w]+?<\/tr>/g)];
var data = [];
for (var i=0;i<trs.length;i++){
var tds = [...trs[i][0].matchAll(/<(td|th)[\s\S\w]+?<\/(td|th)>/g)];
var prov = [];
for (var j=0;j<tds.length;j++){
donnee=tds[j][0].match(/(?<=\>).*(?=\<\/)/g)[0];
prov.push(stripTags(donnee));
}
data.push(prov);
}
return(data);
}
function stripTags(body) {
var regex = /(<([^>]+)>)/ig;
return body.replace(regex,"");
}