【问题标题】:IMPORTJSON in Google Sheet sometimes not getting dataGoogle Sheet 中的 IMPORTJSON 有时无法获取数据
【发布时间】:2018-05-28 11:54:26
【问题描述】:

我创建了一张表格来保存我的加密资产。我使用我在 youtube 上找到的这个 importJSON 函数:(我已经为自己更改了帮助文本)

/**
* Imports JSON data to your spreadsheet Ex: IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1/?convert=EUR","data/quotes/EUR/price")
* @param url URL of your JSON data as string
* @param xpath simplified xpath as string
* @customfunction
*/
function IMPORTJSON(url,xpath){

  try{
    // /rates/EUR
    var res = UrlFetchApp.fetch(url);
    var content = res.getContentText();
    var json = JSON.parse(content);

    var patharray = xpath.split("/");
    //Logger.log(patharray);

    for(var i=0;i<patharray.length;i++){
      json = json[patharray[i]];
    }

    //Logger.log(typeof(json));

    if(typeof(json) === "undefined"){
      return "Node Not Available";
    } else if(typeof(json) === "object"){
      var tempArr = [];

      for(var obj in json){
        tempArr.push([obj,json[obj]]);
      }
      return tempArr;
    } else if(typeof(json) !== "object") {
      return json;
    }
  }
  catch(err){
      return "Error getting data";  
  }

}

我使用这个函数来读取一个 API: 这是我的一段脚本:

  var btc_eur = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1/?convert=EUR","data/quotes/EUR/price");
  var btc_btc = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1/?convert=BTC","data/quotes/BTC/price");
  ss.getRange("B2").setValue([btc_eur]);
  ss.getRange("H2").setValue([btc_btc]);

  var bhc_eur = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1831/?convert=EUR","data/quotes/EUR/price");
  var bhc_btc = IMPORTJSON("https://api.coinmarketcap.com/v2/ticker/1831/?convert=BTC","data/quotes/BTC/price");
  ss.getRange("B3").setValue([bhc_eur]);
  ss.getRange("H3").setValue([bhc_btc]);

最近几天我收到“获取数据时出错”错误。当我手动启动脚本时,它可以工作。

我尝试了我在这里找到的这段代码:

ImportJson

function IMPORTJSON(url,xpath){
  var res = UrlFetchApp.fetch(url);
  var content = res.getContentText();
  var json = JSON.parse(content);
  var patharray = xpath.split("/");
  var res = [];
  for (var i in json[patharray[0]]) {
    res.push(json[patharray[0]][i][patharray[1]]);
  }
  return res;
}

但这给出了一个错误:TypeError: Cannot read property "quotes" from null。我做错了什么?

【问题讨论】:

    标签: google-apps-script google-sheets custom-function


    【解决方案1】:

    最大的问题是您的脚本调用 API 至少 4 次。当少数用户也这样做时,Google 服务器调用 API 的次数过多。

    Coinmarketcap 的 API 带宽有限。当任何客户端达到此限制时,API 将返回 HTTP error 429。 Google Scripts 在共享的 Google 服务器上,这意味着很多用户看起来像是 Coinmarketcap API 的一个客户端。

    当 API 拒绝您的请求时,您的脚本将失败 - 错误消息对应于假定的错误(xpath 无法在空变量中找到 quotes 组件)。

    这是无情的行为。请不要通过大量调用破坏 API。

    您可以一次从 API 加载数据,然后将其重新用于数据中的每个发现。

    我有类似的从 Coinmarketcap API 自动填充的电子表格,您可以将其复制为您的:

    我的脚本在整个运行时严格要求 API 只询问一次,并对所有查询重复使用一个响应。

    更改脚本

    您还可以对代码进行一些更改以节省资源:

    从此更改IMPORTJSON 函数:

    function IMPORTJSON(url,xpath){
        var res = UrlFetchApp.fetch(url);
        var content = res.getContentText();
        var json = JSON.parse(content);
    ...
    

    到这里:

    function IMPORTJSON(json, xpath) {
    ...
    

    你可以像这样更改代码的 rutime 部分:

    var res = UrlFetchApp.fetch("https://api.coinmarketcap.com/v2/ticker/1/?convert=EUR");
    var content = res.getContentText();
    var json = JSON.parse(content);
    
    var btc_eur = IMPORTJSON(json,"data/quotes/EUR/price");
    var btc_btc = IMPORTJSON(json,"data/quotes/BTC/price");
    ss.getRange("B2").setValue([btc_eur]);
    ss.getRange("H2").setValue([btc_btc]);
    ...
    

    主要好处是:UrlFetchApp.fetch 只被调用一次。

    是的,我知道,此代码不像您的那样 1:1 有效。那是因为它只接收欧元而不是比特币的价格。自然而然地获取 BTC 和 BTC 之间的比较是不必要的,因为它始终是 1 和其他值,您可以从 EUR 响应中计算出其他值——请不要滥用 api 进行此类查询。

    【讨论】:

      【解决方案2】:

      正如 Jakub 所说,主要问题是所有请求都被视为来自同一个 Google 服务器。

      我认为更简单的一个解决方案是将代理服务器放在中间,这可以通过购买服务器并设置它(这非常复杂)或使用像 Proxycrawl 这样的服务来完成,其中包括一些免费请求和之后,除非您每月运行数千次查询,否则每月花费不到 1 美元。

      为此,您只需编辑一行脚本:

      var res = UrlFetchApp.fetch(url);
      

      这一行,变成这样:

      var res = UrlFetchApp.fetch(`https://api.proxycrawl.com/?token=YOUR_TOKEN&url=${encodeURIComponent(url)}`);
      

      确保将 YOUR_TOKEN 替换为您的实际服务令牌

      这个简单的更改将使请求永远不会失败,因为每个请求都将从不同的 IP 发送,而不是全部来自 Google。

      【讨论】:

        猜你喜欢
        • 2022-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-05
        相关资源
        最近更新 更多