使用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的):

  1. 使用用户自己的账号,简单来讲就是通知用户授权,然后用户确认后可以拿到用户的access_token读取该用户拥有读取权限的表格数据。
  2. 使用服务账号,将表格共享给这个谷歌账号,然后使用服务器登录服务账号,获取服务账号的access_token读取表格数据。

刚开始的时候我使用了第一种方式,但是出现了下面的缺点:

  1. 需要写死一个账号,每次都是用这个账号进行授权。
  2. access_token 的有效期很短(一般是两个小时),隔一段时间需要手动授权,需要人工的干预。
  3. 要是哪天我的账号被删除了就需要重新设置新的账号,并生成新的项目配置。

后来看到谷歌在服务器授权的时候,建议使用服务账号(虽然API KEY也可以),就实现了服务端无用户参与的授权。

实现

一、创建一个项目

在开发者控制台创建一个项目

link:https://console.developers.google.com/projectcreate

image.png

填写完必要的信息后,直接点击创建即可(注意项目的id不能修改)。

二、开通Google Sheet API服务

在创建完账号以后就会跳转到该项目的dashboard,如下面的视图,直接在搜索框搜索Google Sheet API,如果不开启创建的服务账号是没有权限读取表格数据的。

image.png

在API页面直接点击启用即可开启该项目的Sheet API功能。

image.png

三、生成一个服务账号

开启Sheet API以后会跳转到Sheet API的配置页面,我们现在为这个项目创建一个服务账号。

image.png

首先按照标记点击"凭据",然后点击"API与服务中的凭据"来创建服务账号。
我们在这里选择创建"服务账号密钥";

image.png

四、生成凭据

点击上面的"服务账号密钥"跳转到了密钥创建页面,我们选择新的服务账号,根据自己的要求进行填写,如下所示。

这里我选择了JSON格式,方便Node.js(本次以Node.js作为实践)读取;

image.png

点击创建以后我们会得到一个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

image.png

在上面选择你的项目,就能看到右边的电子邮件,将谷歌表格共享给改邮箱就可以访问了。

参考文档

留下回复