使用Node.js快捷读取谷歌表格数据
前言
随着谷歌表格API升级到第四个版本以后,虽然提供了更快的表格数据读取API,但是还有就是需要授权才能读取到数据,即使是发布到网络的表格。所以我们在做这一升级的时候,尝试了很多的方法,也走过了很多的坑,下面我就简单总结一下。
方案
首先我找到了读取表格数据的API 接口:
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get
该接口需要的参数如下(必传的参数):
{
"spreadsheetId": "",
"range": "",
"access_token": ""
}
使用过的朋友都知道,spreadsheetId和range是表格的id和表格的tab范围。但是access_token并不是一个固定的东西,所以我研究了google获取access_token的两种方式(都是基于OAuth 2.0的):
- 使用用户自己的账号,简单来讲就是通知用户授权,然后用户确认后可以拿到用户的access_token读取该用户拥有读取权限的表格数据。
- 使用服务账号,将表格共享给这个谷歌账号,然后使用服务器登录服务账号,获取服务账号的access_token读取表格数据。
刚开始的时候我使用了第一种方式,但是出现了下面的缺点:
- 需要写死一个账号,每次都是用这个账号进行授权。
- access_token 的有效期很短(一般是两个小时),隔一段时间需要手动授权,需要人工的干预。
- 要是哪天我的账号被删除了就需要重新设置新的账号,并生成新的项目配置。
后来看到谷歌在服务器授权的时候,建议使用服务账号(虽然API KEY也可以),就实现了服务端无用户参与的授权。
实现
一、创建一个项目
在开发者控制台创建一个项目
link:https://console.developers.google.com/projectcreate
填写完必要的信息后,直接点击创建即可(注意项目的id不能修改)。
二、开通Google Sheet API服务
在创建完账号以后就会跳转到该项目的dashboard,如下面的视图,直接在搜索框搜索Google Sheet API,如果不开启创建的服务账号是没有权限读取表格数据的。
在API页面直接点击启用即可开启该项目的Sheet API功能。
三、生成一个服务账号
开启Sheet API以后会跳转到Sheet API的配置页面,我们现在为这个项目创建一个服务账号。
首先按照标记点击"凭据",然后点击"API与服务中的凭据"来创建服务账号。
我们在这里选择创建"服务账号密钥";
四、生成凭据
点击上面的"服务账号密钥"跳转到了密钥创建页面,我们选择新的服务账号,根据自己的要求进行填写,如下所示。
这里我选择了JSON格式,方便Node.js(本次以Node.js作为实践)读取;
点击创建以后我们会得到一个json文件,注意改json文件一定要保存好了,后面的授权全靠它了。
接下来就开始编码实现读取的功能了;
五、开始编码
下面是Node.js作为实现,首先需要安装googleapis。
npm install googleapis --save
相关代码:
const {google} = require('googleapis');
// 后面的json文件就是我们在上面第四步下载的json文件。
const {client_email: email, private_key: key} = require('./service-account.json');
// 指定权限,这里仅需要读取权限就可以了
const scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
// 全局存储授权后的token信息,后面也可以存储到redis等缓存中,现在为了测试,我就存储在本地的变量中
let token = null;
module.exports = {
authorize() {
return new Promise((resolve) => {
// 首先判断有没有token文件
if (token) {
const {access_token, expiry_date} = token;
// 看看有没有过期 + 1分钟
if (expiry_date > (new Date().getTime() + 60 * 1000)) {
return resolve(access_token);
}
}
// 重新授权
let jwtClient = new google.auth.JWT(email, null, key, scopes);
// 直接可以获取到access_token,很方便,不需要人工干预
jwtClient.authorize().then(data => {
// 保存token到全局变量
token = data;
// 返回token
resolve(data.access_token)
}).catch(() => {
resolve('');
});
});
}
};
然后我们通过上面的authorize可以取到token信息,最后使用ajax客户端来调用表格的接口,即可实现数据的读取。
为了保证隐私,我没有上传项目配置的json文件;
参考git实现:https://github.com/gslnzfq/develop-tools-server
六、测试
如果读取数据的时候,google返回了403,那可能是因为你没有将表格共享给服务账号,查看服务账号:
https://console.developers.google.com/iam-admin/serviceaccounts
在上面选择你的项目,就能看到右边的电子邮件,将谷歌表格共享给改邮箱就可以访问了。