【问题标题】:Google Sheets Script Timeout WorkaroundGoogle 表格脚本超时解决方法
【发布时间】:2018-03-30 12:50:27
【问题描述】:

我正在构建一个脚本,该脚本使用循环 ImportHTML 命令根据邮政编码从网络抓取天气数据,目前遇到每次运行脚本时执行超时的问题 .

我设置脚本的当前方式在运行时会产生正确的结果,但鉴于脚本从数百个来源中提取数据,它需要一段时间并且不会在 Google 脚本的当前时间限制内完成。

运行脚本的工作表使用 3 个选项卡:

  1. ZIPS,其中包含从 要从中提取天气数据的站点
  2. Blank,这只是一个用于脚本执行的中间表
  3. Result,最终输出要放置的地方

为了尽量减少读/写量,我将代码从在 ImportHTML 命令执行时写入每个结果改为附加到数组并在末尾写入该数组脚本。当前形式的代码如下:

function getTemps() {
var googleSheet = SpreadsheetApp.getActive();

// Read in Zip code link values
var sheet = googleSheet.getSheetByName('ZIPS');   
var zipArray = sheet.getDataRange().getValues();
var arrayLength = zipArray.length;

//Set up sheet values
var blankSyntaxA = 'ImportHtml("https://www.wunderground.com/cgi-bin/findweather/getForecast?query=pz:';
var blankSyntaxB = '&zip=1", "table", 1)';
var tempResult = [];


// Writing Section

var sheet = googleSheet.getSheetByName('Blank'); 

for (var i = 0; i < arrayLength; i++)
  { 
     var liveSyntax = blankSyntaxA+zipArray[i][0]+blankSyntaxB;
     sheet.getRange('A1').setFormula(liveSyntax);
     var importedData = sheet.getDataRange().getValues();
     tempResult = tempResult.concat(importedData);
  }  
  var sheet = googleSheet.getSheetByName('Result');
  sheet.getRange(1,1,tempResult.length,8).setValues(tempResult);
}

我知道脚本的运行时间可以通过消除 For 循环中包含的读/写来减少,但我不确定如何在不运行“空白”表中的 ImportHTML 命令的情况下获取必要的 HTML 表.有没有办法在不写入工作表的情况下运行该命令来填充“importedData”数组?

另外,我考虑过检查函数的运行时间并在它接近约 5 分钟的运行时间限制时实现中断,然后递归调用回原始函数,但我不确定这是否实际上会缓解运行时问题,或者考虑到递归调用的性质,甚至是可能的。

任何关于如何修改此脚本以在脚本超时参数内运行或修改以产生具有所有必要导入数据的完整预期结果的建议,我们将不胜感激。谢谢!

【问题讨论】:

  • 我可能是错的,但不是因为wunderground.com 中的服务加载过多而产生超时吗?我试着打开它,它已经五分钟没有响应了
  • 我在互联网浏览器中打开 wunderground.com 的服务没有任何问题,所以不确定它是否会出现在服务端。然而,脚本运行的最大阻碍似乎是在 for 循环运行时加载 ImportHTML 命令所需的时间。所以我不确定这是否与服务端有关,或者这是否只是运行重复命令调用并在循环的每次迭代中读取/写入结果的本质。
  • 难道没有一种方法可以通过一次调用服务来获取所需的所有数据吗? (可能传递多个邮政编码或类似的东西)
  • 我认为这就是我目前所坚持的。该网站的设置方式是邮政编码前 3 位数字的链接列表,可在此处找到:wunderground.com/weather-by-zip-code.asp 单击链接会打开一个 html 表格,其中包含与链接前 3 位数字匹配的位置的天气数据,像这样:wunderground.com/cgi-bin/findweather/…我希望拉这张桌子,特别是“地点”和“温度”。列,对于每个链接,但我不确定如何通过一次拉动来完成此操作,或者是否有可能。
  • 但是,您是想获取每个邮政编码的信息还是只需要一些? ImportHTML 通过接收urltype_of_html_structureindex_of_said_structure_on_the_code 工作,这允许您通过调用ImportHtml("https://www.wunderground.com/weather-by-zip-code.asp", "list", 18) 获取所有可用的邮政编码。然后,您可以使用您的代码查询每个起始拉链(用零填充它们以完成三位数字)。这将大大减少对服务的调用

标签: google-apps-script google-sheets


【解决方案1】:

有没有办法在不写入工作表的情况下运行该命令来填充“importedData”数组?

IMPORTHMTL 是 Google 表格的内置电子表格功能。 Google Apps 脚本无法运行/评估此类函数。

相关

另外,我考虑过检查函数的运行时间并在它接近约 5 分钟的运行时间限制时实现中断,然后递归调用回原始函数,但我不确定这是否实际上会缓解运行时问题,或者考虑到递归调用的性质,甚至是可能的。

这是一种解决方法,而不是“缓解者”。有几种技术,例如批处理和并行处理。

参考

answerThreading in Google App Script

Bruce Mcphearson 有一个很好的例子。他的榜样 Parallel Processing in Apps Script 使用 运动中的 Map Reduce。他也在使用触发器,但也许 可能会提供一些不同的视角。

另一种方法是登录Early Access Program 将执行时间限制延长至 30 分钟。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-08
    • 1970-01-01
    相关资源
    最近更新 更多