为什么 UrlFetchApp 在这种情况下无法获取内容?

Why is UrlFetchApp unable to fetch content in this case?

我希望将一些文件保存到我的 Google 驱动器中。但是 UrlFetchApp.fetch 不会得到任何响应并且会超时。我怎么知道这里出了什么问题?

var url = 'https://www.cmegroup.com/CmeWS/exp/voiProductsViewExport.ctl?media=xls&tradeDate=20210702&assetClassId=2&reportType=F&excluded=CEE,CEU,KCB';
var response = UrlFetchApp.fetch(url);

Logger.log(response.getResponseCode())

var folder = DriveApp.getFolderById(folderID); // omitting folderID in this snippet
var file = folder.createFile(response.getBlob());
file.setName('file.xls');

听起来 CME 可能阻止了 Apps 脚本。

今天看到几个这样的问题

对于 CME 阻塞(如果是这种情况),您无能为力,但有一种方法可以解决此问题,即使它需要访问浏览器。我注意到如果我使用 JavaScript fetch API,它会 return XLS blob 正确,所以这里是使用 Apps Script Web App 的解决方法。

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    
  </body>

  <script>
    const r = fetch('https://www.cmegroup.com/CmeWS/exp/voiProductsViewExport.ctl?media=xls&tradeDate=20210702&assetClassId=2&reportType=F&excluded=CEE,CEU,KCB')
    .then(r => r.blob())
    .then(b => readFile(b))
    .then(result => saveToDrive(result))

    function saveToDrive(base64) {
      google.script.run
        .withSuccessHandler(() => console.log("success"))
        .saveAsXLS(base64)
    }

    function readFile(blob){
      return new Promise((resolve, reject) => {
        var fr = new FileReader();  
        fr.onload = () => {
          resolve(fr.result)
        };
        fr.onerror = reject;
        fr.readAsDataURL(blob);
      });
    }

  </script>

</html>

Code.gs

function doGet(){
  return HtmlService.createHtmlOutputFromFile("index")
}

function saveAsXLS(dataURL){
  const parts = dataURL.split(",")
  const type = (parts[0]).replace('data:','');
  const blob = Utilities.newBlob(Utilities.base64Decode(parts[1], Utilities.Charset.UTF_8), type, "sheet.xls")

  DriveApp.createFile(blob)
}

基本上,它不是使用 UrlFetchApp,而是使用浏览器实例来使用 JavaScript fetch API 来获取 blob,然后在将其发送到 Apps 之前对其进行编码脚本方面。然后 Apps 脚本端对其进行解码并将其保存到云端硬盘。

警告

尽管此时您也可能使用 curl 或 Python,因为您必须实际访问 Web 应用程序才能执行它。

参考