Skip to content

Datafocus HTTP源使用说明

简介

通用API源是一个支持用户编写javascript脚本,请求API数据并导入到Datafocus的API源功能。系统内置了ECMAScript5.1,允许用户使用javascript直接再Datafocus中请求外部API,而不需要额外自己实现API数据对接的服务。

通用API源功能不仅实现了基础的请求配置,让用户能够轻松接入各种API资源,更允许用户借助JavaScript脚本,执行更为复 杂、个性化的数据接入流程。通过灵活的配置与定制,用户能够实现对外部数据资源的精准获取与高效 利用。本指南将详细阐述该功能的使用方法,帮助用户快速上手并充分利用这一强大工具,以满足多样化的数据处理需求。

快速入门

本指南将会通过使用通用API功能创建一个简单的API源。通过这个教程,你将会从一个API中获取10快问快答的问题,并把数据保存到Datafocus。

基本要求

需要你已经会使用Datafocus的基础功能,包括页面操作,数据表操作等。

创建通用API

点击【数据表管理】-【外部数据源】-【HTTP数据源】-【新增】,创建通用API。

设置当前HTTP源的名称

在url地址栏中输入请求地址,https://opentdb.com/api.php?amount=10

点击**【测试请求】**可以测试当前接口并获取接口的返回数据。

点击**【保存】**,保存HTTP源后才可进入下一步配置。

点击**【下一步】**,列解析映射配置页面,在该页面用户需要完成从API接口数据到数据表列的映射。列数据通过与一段JSONPath绑定,实现列的映射。

注:主键是必填项,拥有相同主键的数据会被更新覆盖。

主键列名类型JSONPath
🔑问题string$.results[*].question
难度string$.results[*].difficulty
正确答案string$.results[*].correct_answer
错误答案string$.results[*].incorrect_answers
类型string$.results[*].type
问题分类string$.results[*].category

点击**【导入】,输入源导入的表名,这里我们使用和HTTP源同样的名称,点击【确定】**。

此时可以看到新创建的表API_Question,但此时表还没有真正导入。点击**【配置】,点击【立即导入】**,等待表导入成功。

等待30秒左右后,点击**【预览数据】**,可以看到API数据被成功导入。

流程

HTTP源支持 ECMA5.1版本的JavaScript语法,允许用户灵活运用JS脚本,实现复杂的 API接入场景。

变量与上下文

整个HTTP源共用一个上下文,定义的变量所有配置想使用,只需要使用****双大括号框住变量,才调用请求时会将变量替换成变量值。如在url地址中输入变量:

在**【前置操作】【后置操作】【循环条件】中可以写入JavaScript脚本功能,三个脚本段共用上下文。建议在【前置操作】**中定义变量,在其他操作中只修改变量。

生命周期

当用户配置了JavaScript脚本后,在执行调用API请求时,Datafocus后台会为创建一个独立的JavaScript上下文环境,并按照前置操作、请求API、后置操作、循环条件的顺序依次执行,如果满足循环条件,将循环执行后三个环节(即请求API、执行后置操作、判断循环条件)。参考上图。

前置脚本

前置脚本将会在请求API前执行,用户可以在这里实现定义变量、初始化值、获取token等操作。前置脚本只会在开始时执行一次。

后置脚本

后置脚本将会在API请求结束后执行,用户可以通过内置变量responseData,获取到API返回的数据。用户可以在这里对数据进行二次加工处理。

循环条件

循环条件脚本需要用户实现一个loop函数,该函数的返回值将决定请求是否会循环调用,返回true是请求将会循环,返回false是将跳出循环。

测试请求

点击**【测试请求】**按钮,将会触发一次API请求,并检验前置脚本、后置脚本、循环条件、变量解析是否正确加载。响应结果将会显示在下方,内容包含上下文中的变量信息、发送请求的真实值、响应数据、控制台打印信息。

注:测试请求中,仅测试循环条件语法是否正确, 即使循环条件返回true,测试API请求时也仅会执行一次。在正式导入数据时,循环条件才会真正生效。

内置变量与函数

JavaScript中内置了一些功能函数和变量,帮助用户在请求API数据时实现一些必要的功能,如发送http 请求、使用哈希函数完成签名等。这些内置函数都在$对象下,调用方法如下:

javascript
// 对文本签名加密
var msg = "文本信息"
var key = "123456";
var sign = $.sha1(key, msg);

// 发送GET请求
$.get(url, function(data){console.log(data)});

// 发送POST请求
$.post(url, {
	data: {nane: 'datafocus'},
	success: function(data){ console.log(data) },
 	error: function(err) { console.log(err) }
})

内置变量与函数列表

函数/变量说明
$.get(url, data | callback:(data:object)=>{}))get请求
$.post(url, data | callback:(data:object)=>{}))post请求
$.encodeBase64(string)base64编码, 返回字符串
$.decodeBase64(string)base64解码, 返回字符串
$.md5(strOrBytes)MD5函数,返回字符串
$.sha1(strOrBytes)SHA1哈希函数,返回字符串
$.sha256(strOrBytes)SHA256哈希函数,返回字符串
$.hmacSha1(key, msg)HMAC-SHA1哈希加密函数,返回字符串
$.hmacSha256(key, msg)HMAC-SHA256哈希加密函数,返回字符串
$.strToHex(text)Hex字符串转HexBytes, 返回bytes
$.hexToStr(bytes)HexBytes转Hex字符串, 返回字符串
$.encodeStr(text, encoding='utf-8')字符串编码,默认utf-8, 返回bytes
$.decodeStr(bytes, encoding='utf-8')字符串解码,默认utf-8, 返回字符串
$.getStorageValue()增量导入时,获取上次存储的记录值
$.setStorageValue(text)增量导入时,存储本次记录值
responseData存储API请求返回数据的变量

示例

JavaScript变量使用

在配置项中使用JavaScript定义的变量,并使用脚本动态赋值。

在【前置脚本】中定义一个变量pageNum,在Params参数中可以使用双大括号**来使用变量。在请求时,**会被解析为pageNum变量的实时值。

前置脚本

javascript
var pageNum=1;

循环请求

描述

遍历请求API数据时常见的使用场景,通过设置循环条件实现API请求的循环调用。

示例

在【前置脚本】中定义变量pageNum,用于指定请求的页数。并在【循环条件】中实现翻页和是否结束循环判断。

前置脚本

javascript
var pageNum=1;

循环条件

javascript
function loop(){
  // loop condition here
  pageNum++;  // pageNum加1实现翻页
  return responseData.values.length()!=0  // 如果还有数据,就继续循环调用,直到数据返回为空
}

在Params配置中绑定pageNum的值为pageNum变量。此时保存并导入表,正式导入表时API请求将会循环导入。

注:测试请求中,不会真实循环请求API,仅在正式导入数据时,循环条件才会真正生效。

数据预处理

描述

响应的数据可能并不能总是满足我们使用JSONPath映射到列的需求,如下方的天气数据。用户想抽取的数据为province,city,date,weather,但是province,city信息与date,weather信息并不在json对象的同一级,此时直接使用JSONPath去提取映射,会导致数据错位和丢失。此时我们需要对数据先进行处理,再对数据做映射。

json
{
  "count": "1",
  "infocode": "10000",
  "status": "1",
  "info": "OK",
  "forecasts": [
    {
      "province": "浙江",
      "city": "杭州市",
      "adcode": "310000",
      "reporttime": "2024-12-17 10:38:08",
      "casts": [
        {
          "date": "2024-12-17",
          "weather": "晴",
          "wind": "西北",
          "week": "2",
          "power": "1-3",
          "temp": "-1"
        },
        {
          "date": "2024-12-18",
          "weather": "晴",
          "wind": "西",
          "week": "3",
          "power": "1-3",
          "temp": "-5"
        },
        {
          "date": "2024-12-19",
          "dayweather": "晴",
          "daywind": "西南",
          "week": "4",
          "power": "1-3",
          "temp": "0"
        }
      ]
    }
  ]
}

示例

在【后置脚本】用户可以通过responseData变量获取到响应的json数据。

前置脚本

javascript
var forecasts=[];

后置脚本

javascript
// 循环遍历解析responseData数据,把分布在不同层的数据规整到一维数组中。
for (var i = 0; i < responseData.forecasts.length; i++) {
  var city = responseData.forecasts[i];
  for (var j = 0; j < city.casts.length; j++) {
    var item = city.casts[j];
    forecasts.push({
      province: city.province,
      city: city.city,
      date: item.date,
      dayweather: item.weather,
      daywind: item.daywind
    });
  }
}
responseData = forecasts;  // 将规整后的数据做为响应数据

处理后的响应数据

json
[
  {
    "province": "浙江",
    "city": "杭州市",
    "date": "2024-12-17",
    "weather": "晴"
  },
  {
    "province": "浙江",
    "city": "杭州市",
    "date": "2024-12-18",
    "weather": "晴"
  },
  {
    "province": "浙江",
    "city": "杭州市",
    "date": "2024-12-19",
    "dayweather": "晴"
  }
]

此时我们再使用JSONPath映射列,就不会出现映射错位或数据丢失的问题。

主键列名类型JSONPath
🔑日期string$[*].date
🔑省份string$[*].province
🔑城市string$[*].city
天气string$[*].weather

数据签名与认证

描述

市面上绝大部分API都要求用户进行身份校验,HTTP源内置了常用的签名加密函数,供用户实现API的签名认证。

示例

在此示例中,用户需要根据第三方接口平台提供的appIdappKey,先获取token信息再请求API数据,且每次请求都需要对参数进行签名加密。

  1. AKSK常量定义;
  2. 获取第三方token认证;
  3. 请求第三方接口实现签名认证。
javascript
// 1.定义第三方接口请求认证信息
var appId = "0GEm********1XkH";
var appKey = "pLsv************************6Y2q";
var timestamp = parseInt((new Date()).valueOf()/1000);
var sign = appId+timestamp;
var token;
// 2.获取token
$.post("https://open.******.com/api/tokens", 
	{client_id: appId,
 	 stamp: timestamp,
 	 sign: $.sha1(appKey, sign)},  // 使用sha1完成签名
	function(data){
 		token = data['Data']; // 获取返回的token
 	}
);
// 定义参数变量
var pIndex = 1;
var pSize = 100;
var total = 1;
// 3.实现获取数据接口签名
timestamp = (new Date()).valueOf();
var params = "_stamp="+timestamp+"&_token="+token+"&pindex="+pIndex+"&psize="+pSize;
var sign = $.sha1(appKey, params); // 使用sha1完成签名

增量导入

描述

API导入的速度与数据库直连导入的速度相差甚远,且考虑到API服务方的流量使用情况,在数据量大的情况下,增量导入是我们首先考虑的解决方案。

示例

以获取天气数据为例,每次增量导入数据时,用户都想基于上次导入时间节点,增量导入这段时间新增的天气数据。因此我们需要记录上次导入的时间信息,并传递参数给API,请求指定时间段内的数据。

用户可以使用内置**$.setStorageValue(value)方法存储45个字符以内的值,用于记录一次导入任务的截至点;使用内置$.getStorageValue()方法获取上次存储的截至信息。如果从未存储过信息,则获取到undefined**。

前置脚本

javascript
function formateDate(dt){
    """Date转日期字符串"""
    var year = dt.getFullYear();
    var month = ('0' + (dt.getMonth() + 1)).slice(-2);
    var day = ('0' + dt.getDate()).slice(-2);
    return year + '-' + month + '-' + day;
}
// 使用getStorageValue函数,获取上次的存储
var lastTime = $.getStorageValue();
if(lastTime == undefined){
    lastTime = "2024-01-01";
}
// 
var updateTime = formateDate(new Date());

配置参数

在参数中应用上次的存储的值用作增量更新的过滤条件

后置脚本

javascript
// 在后置脚本中,使用setStorageValue函数,存储本次增量更新时间节点
$.setStorageValue(updateTime);

增量导入配置

以上设置完HTTP源之后,还需要将表的导入方式设置为增量导入。全量导入在启动任务前会清空数据表,而增量导入则会保留数据,且只有开启了增量导入,setStorageValue的值才会真正被保存下来。

常见问题

循环条件没有生效

Q: 为什么测试请求的时候,结果没有循环调用?

A: 在测试请求中,仅会检测循环条件语法是否正确,并请求一次接口,而不会真的循环请求。只有正式导入数据时,循环条件才会真正生效。

为什么导入数据少了或只有部分数据

Q: 为什么导入的数据只有部分数据

A1: API导入表主键值唯一,当出现重复主键时,新导入的值会覆盖旧值。可以设置多主键并确保联合主键唯一,则不会出现值相互覆盖的情况。

A2: 数据在json的不同层级中,导致JSONPath解析出来的数据匹配不上。需要对数据处理后使数据层级一致后再使用JSONPath列映射。详见

为什么修改了联合主键,导入数据还是少了

Q: 修改HTTP源配置时,调整了主键,但是没有生效。

A: 修改主键后,表需要重建才能生效,需要在编辑后点击**【重新导入】**,才会使新的主键配置生效,且此时所有数据都将被置空,需要重新导入。