Google表格中的IMPORTJSON有时无法获取数据

时间:2018-05-28 11:54:27

标签: google-apps-script google-sheets

我创建了一张表来保存我的加密资源。我使用我在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]);

我得到的最后几天&#34;错误获取数据&#34;错误。当我开始手动编写它的脚本时。

我试过这个我在这里找到的代码:

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:无法读取属性&#34;引号&#34;从null。我做错了什么?

2 个答案:

答案 0 :(得分:1)

最大的问题是你的脚本调用API至少4次。当很少有用户这样做时,Google服务器调用API太多次了。

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

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

这是无情的行为。请不要通过群发电话破坏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和BTC之间的比较是不必要的,因为它总是1和其他值,您可以从EUR反应中进行数字计算 - 请不要滥用api进行此类查询。

答案 1 :(得分:0)

正如 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。