簡體   English   中英

如何在從 API 端點獲取數據到 Google 表格時處理 Google Apps 腳本 6 分鍾執行時間限制?

[英]How to handle Google Apps script 6 minute execution time limit while fetching data from an API endpoint to google sheets?

我必須從 API 獲取數據到谷歌表格,這應該是 plot 近 1600 個條目。 但是,執行在 6 分鍾時停止,僅繪制大約 1000 個條目。 我在 Apps 腳本中的初始代碼是:

function myFunction() {
  var spreadsheet=SpreadsheetApp.getActive();
  var sheet=spreadsheet.getActiveSheet();
  var nextPage=1;
  sheet.clear();


  var headerRow=["ID","NAME","SOURCE","STATUS","PRICING_MIN_PRICE","PRICING_MAX_PRICE","LOACTION_COUNTRY","LOACTION_LOCALITY","IMAGES_COUNT","VIDEOS_COUNT","FEATURES_COUNT"];
  sheet.appendRow(headerRow);
  sheet.getRange(
    spreadsheet.getCurrentCell().getRow(),
    1, 1, sheet.getMaxColumns()).activate();
  spreadsheet.getActiveRangeList().setFontWeight('bold');
  

  
  var curr;
  while(nextPage){
    curr=nextPage;
    var apiURL=`https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=10&sort_key=relevance&sort_order=desc&statuses=active`;
    var response=UrlFetchApp.fetch(apiURL);
    var json=response.getContentText();
    var dataPoints=JSON.parse(json);
    var resArray=dataPoints.data.result;
    for(var i=0;i<resArray.length;i++){
      var id=resArray[i].id!=null?resArray[i].id:"";
      var name=resArray[i].name!=null?resArray[i].name:"";
      var source=resArray[i].source!=null?resArray[i].source:"";
      var status=resArray[i].status!=null?resArray[i].status:"";
      var pricing_min_price=resArray[i].pricing?resArray[i].pricing.min_price:"";
      var pricing_max_price=resArray[i].pricing?resArray[i].pricing.max_price:"";
      var location_country=(resArray[i].location&&resArray[i].location.country)?resArray[i].location.country.long_name:"";
      var location_locality=(resArray[i].location&&resArray[i].location.locality)?resArray[i].location.locality.long_name:"";
      var images_count=resArray[i].images.length;
      var vid_count=resArray[i].videos.length;
      var feature_count=resArray[i].features.length;
      var row=[id,name,source,status,pricing_min_price,pricing_max_price,location_country,location_locality,images_count,vid_count,feature_count];
      sheet.appendRow(row);

    }
    nextPage=dataPoints.data.meta.next;  //for every page the nextPage stores the value of the next page, and for the last page (159 approx),     nextPage=null
  }
  
}

正如我已經提到的那樣,這不起作用。 在網上搜索了一番后,我找到了一些繞過執行時間的方法,我修改了我的代碼,如下所示:

var spreadsheet=SpreadsheetApp.getActive();
var sheet=spreadsheet.getActiveSheet();
var nextPage=1;   //set nextPage as a global variable so that it can be accessed by all functions


function isTimeUp(today) {
  var now = new Date();
  return now.getTime() - today.getTime() > 300000;  //setting up a limit of 5 minutes
}


function myFunction() {

  sheet.clear();

  var today=new Date();

  var headerRow=["ID","NAME","SOURCE","STATUS","PRICING_MIN_PRICE","PRICING_MAX_PRICE","LOACTION_COUNTRY","LOACTION_LOCALITY","IMAGES_COUNT","VIDEOS_COUNT","FEATURES_COUNT"];
  sheet.appendRow(headerRow);
  sheet.getRange(
    spreadsheet.getCurrentCell().getRow(),
    1, 1, sheet.getMaxColumns()).activate();
  spreadsheet.getActiveRangeList().setFontWeight('bold');
  

  
  var curr;
  while(nextPage){

    if (isTimeUp(today)) {
        // schedule a trigger for a different function
        ScriptApp.newTrigger("repeatFunction")
            .timeBased()
            .everyMinutes(5)
            .create();
        break;
    }
    curr=nextPage;
    var apiURL=`https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=10&sort_key=relevance&sort_order=desc&statuses=active`;
    var response=UrlFetchApp.fetch(apiURL);
    var json=response.getContentText();
    var dataPoints=JSON.parse(json);
    var resArray=dataPoints.data.result;
    for(var i=0;i<resArray.length;i++){
      var id=resArray[i].id!=null?resArray[i].id:"";
      var name=resArray[i].name!=null?resArray[i].name:"";
      var source=resArray[i].source!=null?resArray[i].source:"";
      var status=resArray[i].status!=null?resArray[i].status:"";
      var pricing_min_price=resArray[i].pricing?resArray[i].pricing.min_price:"";
      var pricing_max_price=resArray[i].pricing?resArray[i].pricing.max_price:"";
      var location_country=(resArray[i].location&&resArray[i].location.country)?resArray[i].location.country.long_name:"";
      var location_locality=(resArray[i].location&&resArray[i].location.locality)?resArray[i].location.locality.long_name:"";
      var images_count=resArray[i].images.length;
      var vid_count=resArray[i].videos.length;
      var feature_count=resArray[i].features.length;
      var row=[id,name,source,status,pricing_min_price,pricing_max_price,location_country,location_locality,images_count,vid_count,feature_count];
      sheet.appendRow(row);

    }
    nextPage=dataPoints.data.meta.next;  //for every page the nextPage stores the value of the next page, and for the last page (159 approx),     nextPage=null
  }
  
}


function repeatFunction(){
  while(nextPage){
    var curr=nextPage;
    var apiURL=`https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=10&sort_key=relevance&sort_order=desc&statuses=active`;
    var response=UrlFetchApp.fetch(apiURL);
    var json=response.getContentText();
    var dataPoints=JSON.parse(json);
    var resArray=dataPoints.data.result;
    for(var i=0;i<resArray.length;i++){
      var id=resArray[i].id!=null?resArray[i].id:"";
      var name=resArray[i].name!=null?resArray[i].name:"";
      var source=resArray[i].source!=null?resArray[i].source:"";
      var status=resArray[i].status!=null?resArray[i].status:"";
      var pricing_min_price=resArray[i].pricing?resArray[i].pricing.min_price:"";
      var pricing_max_price=resArray[i].pricing?resArray[i].pricing.max_price:"";
      var location_country=(resArray[i].location&&resArray[i].location.country)?resArray[i].location.country.long_name:"";
      var location_locality=(resArray[i].location&&resArray[i].location.locality)?resArray[i].location.locality.long_name:"";
      var images_count=resArray[i].images.length;
      var vid_count=resArray[i].videos.length;
      var feature_count=resArray[i].features.length;
      var row=[id,name,source,status,pricing_min_price,pricing_max_price,location_country,location_locality,images_count,vid_count,feature_count];
      sheet.appendRow(row);

    }
    nextPage=dataPoints.data.meta.next;  //for every page the nextPage stores the value of the next page, and for the last page (159 approx),     nextPage=null
    if (nextPage==null) {
      var triggers = ScriptApp.getProjectTriggers();
      for (var i = 0; i < triggers.length; i++) {
          // delete all triggers
          ScriptApp.deleteTrigger(triggers[i]);
      }
      break;
    }
  }

} 

我嘗試將 nextPage 設置為全局變量並設置一個觸發器,該觸發器每 5 分鍾調用一次 repeatFunction 方法。 然而,這會產生類似無限循環的東西。 數據不斷添加到電子表格中。 我不知道如何克服這個問題,因為我對 Google App Scripts 的概念及其用法不熟悉。 請幫我解決這個問題。 如有需要,請詢問更多詳情。 謝謝!

我相信你的目標如下。

  • 您的myFunction()有效。 但是,您想降低腳本的處理成本。

修改點:

  • 在您的腳本中, appendRow在循環中使用。 我認為這可能是您的問題的原因之一。
  • 盡管我不確定您要使用的 API 的詳細信息,但在端點的查詢參數中,使用了limit=10 而且, I have to fetch data from an API to google sheets which is supposed to plot nearly 1600 entries. ,如果limit=10是一個 API 調用的值的數量,則需要完成 160 個請求。 我認為這將是您問題的另一個原因。 在這種情況下,我想建議修改limit的值。
    • 在此修改中,使用limit=2000 在我的測試中,沒有發生錯誤。 但如果出現錯誤,請修改此值並再次測試。

當以上幾點反映到您的腳本時,它變成如下。

修改后的腳本:

在此修改中,請按如下方式修改您的myFunction()

function myFunction2() {
  var spreadsheet = SpreadsheetApp.getActive();
  var sheet = spreadsheet.getActiveSheet();
  var nextPage = 1;
  sheet.clear();
  var headerRow = ["ID", "NAME", "SOURCE", "STATUS", "PRICING_MIN_PRICE", "PRICING_MAX_PRICE", "LOACTION_COUNTRY", "LOACTION_LOCALITY", "IMAGES_COUNT", "VIDEOS_COUNT", "FEATURES_COUNT"];
  sheet.appendRow(headerRow);
  sheet.getRange(spreadsheet.getCurrentCell().getRow(),1, 1, sheet.getMaxColumns()).activate();
  spreadsheet.getActiveRangeList().setFontWeight('bold');
  var ar = [];
  var curr;
  while (nextPage) {
    curr = nextPage;
    var apiURL = `https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=2000&sort_key=relevance&sort_order=desc&statuses=active`;
    var response = UrlFetchApp.fetch(apiURL);
    var json = response.getContentText();
    var dataPoints = JSON.parse(json);
    var resArray = dataPoints.data.result;
    for (var i = 0; i < resArray.length; i++) {
      var id = resArray[i].id != null ? resArray[i].id : "";
      var name = resArray[i].name != null ? resArray[i].name : "";
      var source = resArray[i].source != null ? resArray[i].source : "";
      var status = resArray[i].status != null ? resArray[i].status : "";
      var pricing_min_price = resArray[i].pricing ? resArray[i].pricing.min_price : "";
      var pricing_max_price = resArray[i].pricing ? resArray[i].pricing.max_price : "";
      var location_country = (resArray[i].location && resArray[i].location.country) ? resArray[i].location.country.long_name : "";
      var location_locality = (resArray[i].location && resArray[i].location.locality) ? resArray[i].location.locality.long_name : "";
      var images_count = resArray[i].images.length;
      var vid_count = resArray[i].videos.length;
      var feature_count = resArray[i].features.length;
      var row = [id, name, source, status, pricing_min_price, pricing_max_price, location_country, location_locality, images_count, vid_count, feature_count];
      ar.push(row);
    }
    nextPage = dataPoints.data.meta.next;  //for every page the nextPage stores the value of the next page, and for the last page (159 approx),     nextPage=null
  }
  sheet.getRange(sheet.getLastRow() + 1, 1, ar.length, ar[0].length).setValues(ar);
}

筆記:

  • 在此修改中,使用setValues代替appendRow ,並使用limit=2000 在這種情況下,1,585 個值由一個 API 調用檢索。 而在我的環境中,上述修改腳本的處理時間約為 20 秒。

參考:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM