如何优化getYoutubeViews函数,以免超出每日的Youtube API配额?

时间:2019-08-14 05:44:57

标签: javascript json google-apps-script google-sheets youtube

我正在尝试自动收集Google电子表格中Youtube视频的统计信息。为此,我在电子表格脚本编辑器中将代码与getYoutubeViews函数以及GETURL,linkURL函数等配合使用。

这是getYoutubeViews函数示例

function getYoutubeViews(videoId){
  var url = "https://www.googleapis.com/youtube/v3/videos?part=statistics&id=" + videoId;
  url = url + "&key=mykey";
  //Utilities.sleep(Math.random(15000))
  var videoListResponse = UrlFetchApp.fetch(url);
  var json = JSON.parse(videoListResponse.getContentText());
  return json["items"][0]["statistics"]["viewCount"];
}

function GETURL(input) {
  var range = SpreadsheetApp.getActiveSheet().getRange(input);
  var url = /"(.*?)"/.exec(range.getFormulaR1C1())[1];
  return url;
}

我遇到两个问题。

当用户加载表时,脚本开始工作。由于表中的视频数超过600个,因此这将启动大量处理。这将导致错误:“服务在短时间内被调用太多次:exec qps”。

但是用Utilities.sleep修复它没有意义,因为还有第二个问题。经过3-4个小时的工作并定期刷新表格,Google的10,000点的API密钥配额就结束了。

我试图最小化列表上的功能和动作,并使用Utilities.sleep来避免此错误:

Service invoked too many times in a short time: exec qps. 
Try Utilities.sleep(1000) between calls. (строка 0).

但这似乎无助于解决配额问题。

在我看来,我可以某种方式将数据保存在单元格中,仅在更新数据时才激活功能。我试图将更改触发器用于这些目的,但是我做错了或没有帮助。

第二个假设是,有可能以某种方式保存先前的数据,这样即使发生脚本错误,单元格中也会有一些数据。但是我不知道该怎么办。

1 个答案:

答案 0 :(得分:1)

避免使用自定义函数(每次都会发出所有请求)的一种方法是使用onOpen()触发器添加菜单[1],单击该菜单即可运行getYoutubeViews()函数。此功能将发出请求,并将响应数据(观看次数)插入电子表格中。它将从B列(从第二行开始)获取videoId,并在D列中设置观看次数。我设置了“ If”条件,以便仅对空视图单元格发出请求(更新值)。

要处理电子表格上的数据,我使用了SpreadsheetApp类[2]

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
  .createMenu('Actions')
  .addItem('Add views', 'getYoutubeViews')
  .addToUi();  
}

function getYoutubeViews(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Sheet2"); 
  var videoIdArray = sheet.getRange(2, 2, sheet.getLastRow()-1, 1).getValues();
  var views = sheet.getRange(2, 4, sheet.getLastRow()-1, 1);

  for(var i=0; i<videoIdArray.length ; i++) {
    var videoId = videoIdArray[i][0];
    var viewsCell = sheet.getRange(2 + i, 4);

    if(viewsCell.getValue() == "") {
      var url = "https://www.googleapis.com/youtube/v3/videos?part=statistics&id=" + videoId;
      url = url + "&key=AAIzaSyAUjC5AchndLg9BRIrRBYKLuKf-fFkMC9M";
      var options = {
        'muteHttpExceptions' : true,
        'headers': {
          'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
        }
      };

      var videoListResponse = UrlFetchApp.fetch(url, options);
      var json = JSON.parse(videoListResponse.getContentText());
      Logger.log(json)

      var views = json["items"][0]["statistics"]["viewCount"];
      viewsCell.setValue(views);
    }
  }
}

您不能使用onEdit()函数直接运行代码,因为触发器有限制[3],其中有一个说:

  

他们无法访问需要授权的服务。

UrlFetchApp.fetch()是一项需要用户授权的服务。

[1] https://developers.google.com/apps-script/guides/menus

[2] https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app

[3] https://developers.google.com/apps-script/guides/triggers/#restrictions