最近有读者在知乎上问起使用R语言调用API接口获取数据的问题,学堂君觉得这块内容确实很重要、很实用,并打算推出一些推文。不过,目前学堂君对此也不甚了解,只能边学边更。
之前学堂就发过一篇调用高德地图API进行地理编码的推文,详见在R语言中使用高德地图的API进行地理/逆地理编码,而本篇介绍的百度翻译的API调用方法其实和这篇内容也差不多。
本篇目录如下:
1 API简介
2 百度翻译API
3 R语言代码
3.1 创建URL
3.2 modify_url函数
3.3 GET函数
3.4 fromJSON函数
3.5 错误示例
3.6 封装成函数
1 API简介
httr
工具包的帮助文档[1]是一个很好的API入门文档。API的使用分为两个部分:
请求(request):用户向服务器发送数据请求;
响应(response):服务器向用户返回所需要的数据内容。
请求方式有很多种,在httr
包中各自对应一个函数,如GET()
、HEAD()
、POST()
、 PATCH()
、PUT()
、DELETE()
,其中GET()
函数是最常用的一个。
用户发送请求时需要创建一个符合要求的URL地址。这个URL地址通常由两部分组成:
第一部分是通用地址,相当于API接口的根目录,如高德地图API的
https://restapi.amap.com/v3/geocode/geo
,百度翻译API的http://api.fanyi.baidu.com/api/trans/vip/translate
;第二部分为查询地址,包含了用户所要查询的字段名称以及用户账号、密码等个性化内容。
2 百度翻译API
在浏览器中打开百度翻译,在上方靠右侧的地方可以看到“翻译API”的入口:
根据网站指引,创建开发者账户,获得一个APP ID和密钥:
在“产品服务”栏有相应的使用说明,以“通用翻译[2]”为例:
打开上面的网址(https://fanyi-api.baidu.com/product/113),可以看到创建百度翻译API的URL的方法以及相关参数说明:
3 R语言代码
3.1 创建URL
下面使用R语言代码实现说明文档中的接入举例,即创建URL。
首先需要准备以下字段(变量):
q = "apple" # 翻译内容
from = "en" # 输入语种
to = "zh" # 输出语种
appid = "2015063000000001" # 用户APP ID
salt = "1435660288" # 随机码
key = "12345678" # 用户密钥
读者需要将
appid
和key
替换成自己申请的账户ID和密钥。
URL的通用地址:
url1 = "https://fanyi-api.baidu.com/api/trans/vip/translate"
生成签名sign
。说明文档中介绍这个过程需要进行MD5加密,在R语言中可以使用openssl
工具包中的md5()
函数:
sign = paste0(appid, q, salt, key)
library(openssl)
sign = md5(sign)
sign
## [1] "f89f9594663708c1605f3d736d01d2d4"
URL的查询地址:
url2 <- paste0("q=",q, "&from=", from, "&to=", to,
"&appid=", appid, "&salt=", salt,
"&sign=", sign)
url2
## [1] "q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4"
拼接形成完整的URL:
url = paste0(url1, "?", url2)
url
## [1] "https://fanyi-api.baidu.com/api/trans/vip/translate?q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4"
需要注意
url1
和url2
之间还有一个?
。
3.2 modify_url函数
上节拼接URL的查询地址的过程显得非常繁琐,我们可以使用httr
工具包中的modify_url()
函数简化这一过程:
library(httr)
url = modify_url("http://api.fanyi.baidu.com/api/trans/vip/translate",
query = list(q = q, from = from, to = to,
appid = appid,
salt = salt,
sign = sign))
url
## [1] "http://api.fanyi.baidu.com/api/trans/vip/translate?q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4"
3.3 GET函数
使用上面创建的url
作为GET()
函数的参数:
GET(url)
## Response [http://api.fanyi.baidu.com/api/trans/vip/translate?q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4]
## Date: 2022-09-04 14:00
## Status: 200
## Content-Type: application/json
## Size: 77 B
输出结果中,Status
为200,表示请求成功;此外,404表示请求文件不存在(file not found),403表示请求被拒绝(permission denied)。
Content-Type
为application/json表示响应数据为json类型,可以使用jsonlite
工具包中的fromJSON()
函数抓取数据(在高德地图API的推文中使用的也是该函数)。
另外,GET()
函数继承了modify_url()
函数的参数,因此3.2节和本节的代码可以合并成如下形式:
GET("http://api.fanyi.baidu.com/api/trans/vip/translate",
query = list(q = q, from = from, to = to,
appid = appid,
salt = salt,
sign = sign))
3.4 fromJSON函数
将url
作为fromJSON()
函数的参数:
library(jsonlite)
fromJSON(url)
## $from
## [1] "en"
##
## $to
## [1] "zh"
##
## $trans_result
## src dst
## 1 apple 苹果
fromJSON(url)$trans_result[1,2]
## [1] "苹果"
3.5 错误示例
请求成功并不意味着就会返回正确的数据。下面代码更改了appid
,使得创建的URL不符合要求(ID和密钥不匹配):
url0 = modify_url("http://api.fanyi.baidu.com/api/trans/vip/translate",
query = list(q = q, from = from, to = to,
appid = "1",
salt = salt,
sign = sign))
GET(url0)
## Response [http://api.fanyi.baidu.com/api/trans/vip/translate?q=apple&from=en&to=zh&appid=1&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4]
## Date: 2022-09-04 14:48
## Status: 200
## Content-Type: application/json
## Size: 54 B
fromJSON(url0)
## $error_code
## [1] "52003"
##
## $error_msg
## [1] "UNAUTHORIZED USER"
错误代码:52003;错误提示:用户账户未授权。
说明文档(https://fanyi-api.baidu.com/product/113)中列举了一些错误代码及解决方案:
3.6 封装成函数
上述过程可以封装成如下函数:
fanyi <- function(q = "apple",
from = "en",
to = "zh",
appid = "",
salt = "1435660288",
key = "",
encoding = "utf-8") { # 新加encoding参数
require(httr)
require(jsonlite)
require(openssl)
sign = paste0(appid, q, salt, key)
sign = md5(sign)
url = modify_url("http://api.fanyi.baidu.com/api/trans/vip/translate",
query = list(q = q, from = from, to = to,
appid = appid,
salt = salt,
sign = sign))
url = url(url, encoding = encoding)
fromJSON(url)$trans_result[1,2]
}
读者需要将
appid
和key
参数替换成自己申请的账户ID和密钥。
示例1:
fanyi()
## [1] "苹果"
示例2:
## 转英语
fanyi("R语言学堂", from = "auto", to = "en")
## [1] "R School of Language"
## 转俄语
fanyi("R语言学堂", from = "auto", to = "ru")
## [1] "R - языковая школа"
## 转西班牙语
fanyi("R语言学堂", from = "auto", to = "spa")
## [1] "Escuela de idiomas R"
参考资料
[1]
httr: Tools for Working with URLs and HTTP: https://mirrors.tuna.tsinghua.edu.cn/CRAN/web/packages/httr/index.html
[2]通用翻译API接入文档: https://fanyi-api.baidu.com/product/113