使用Google Sheets + JavaScript定制一个自动化天气管家
可以根据天气变化每日自动给我们的邮箱发送推送消息的功能?是的,今天我们将只用JavaScript实现这个功能,而GoogleSheets可以做很多事情,不仅仅只是文档的处理工作,这篇文章将给大家具体介绍这个能够让各位JSer施展拳脚的地方。
应用场景
是否在每天出门前被猝不及防的大雨所困扰,今天我们就将使用Google Sheet - 请科学上网-推荐)定制一个判断当天是否可能下雨的邮箱通知云应用,使我们每天都能放放心心的出门!行动起来!
天气预报 API
我们将使用这个Web API在接下来的步骤中来完成我们的一系列网络请求动作。API将会返回标准的JSON格式最近一周内的天气具体数据,这个天气API提供两个参数:
-
loc: 地点 (比如:Beijing 则获得北京最近一周内的天气)
-
deg: 天气度数属性(包括 F or C , 默认是F华氏度,我们则常习惯于摄氏度C)
举例:返回西安最近5天的JSON格式的天气信息。
https://f.stdlib.com/thisdavej/weather/forecast?loc=Xian°=C
将返回如下格式的JSON数据大体结构:
[
{
"low": "5",
"high": "14",
"skycodeday": "27",
"skytextday": "Mostly Cloudy",
"date": "2017-03-10",
"day": "Friday",
"shortday": "Fri",
"precip": "0",
"degType": "C"
},
{
"low": "7",
"high": "15",
"skycodeday": "28",
"skytextday": "Mostly Cloudy",
"date": "2017-03-11",
"day": "Saturday",
"shortday": "Sat",
"precip": "70",
"degType": "C"
},
{
"low": "2",
"high": "9",
"skycodeday": "11",
"skytextday": "Rain",
"date": "2017-03-12",
"day": "Sunday",
"shortday": "Sun",
"precip": "100",
"degType": "C"
},
{
"low": "1",
"high": "6",
"skycodeday": "11",
"skytextday": "Rain Showers",
"date": "2017-03-13",
"day": "Monday",
"shortday": "Mon",
"precip": "100",
"degType": "C"
},
{
"low": "2",
"high": "10",
"skycodeday": "26",
"skytextday": "Cloudy",
"date": "2017-03-14",
"day": "Tuesday",
"shortday": "Tue",
"precip": "100",
"degType": "C"
}
]
根据可以获得天气动态数据,将为我们接下来的步骤提供便利。
创建基本功能函数
我们接下来将在Google Sheets中进行JavaScript的函数创建。首先打开 Google Sheets并且创建一个新的表格文档。
打开工具栏的脚本编辑器选项。
将会进入到Google Sheets自带的JavaScript脚本编辑页面。
让我们先创建我们需要使用的一系列功能函数。
// 对小于10的数自动加前缀0
function padZero (number) {
return number < 10 ? '0' + number:number.toString();
}
因为API返回的天气信息中的date日期中的数字小于10自带0前缀,padZero()
可以让之后我们能更好的获得当日的日期。接下来我们创建我们获得天气数据的函数:
function forecast_today_object(city, threshold) {
var url = 'http://f.stdlib.com/thisdavej/weather/forecast?deg=C&loc=' + encodeURI(city);
var response = UrlFetchApp.fetch(url);// Google自带的网络请求Api
var obj = JSON.parse(response.getContentText()); //parse请求到的JSON数据
// 获得当天的天气预报
// 获得当天的日期
var date = new Date();
var day = padZero(date.getDate());
var month = padZero(date.getMonth() + 1);
var year = date.getFullYear();
var now = year + '-' + month + '-' + day;
var todayObj = obj.filter(function(o) {
return o.date === now;
}); // 获得当天的天气
if(todayObj.length > 0){
var today = todayObj[0];
today.precip = parseFloat(today.precip); // 当日的降雨概率
today.rainLikely = today.precip >= threshold; // 可能下雨的一个判断,当超过一个指定界限时提醒
return today;
} else {
return { error : 'No forecast data found for today'};
}
}
forecast_today_object()
函数使用了Google自带的 UrlFetchApp.fetch方法进行网络请求操作,返回我们需要的天气数据。创建todayObj
对象保存当天的天气信息,并且新增rainLikely
属性,并使其在降雨概率大于预设值时为true
.
下一步创建可供Sheets直接使用的函数,这样可以直接让天气信息显示在表格文档中。
// 此函数可只在文档中直接调用,以便于我们调试我们的数据
function FORECAST_TODAY(city, threshold) {
var today = forecast_today_object(city, threshold);
return JSON.stringify(today, null, 2); // 将JSON信息转换为字符型,并添加2个空格缩进
}
将函数名设为全大写形式,以便我们区分执行函数和功能函数。Ctrl + S
保存我们的脚本,并在表格文档中测试我们的函数功能是否能够正确运行。
A | B | C | |
---|---|---|---|
1 | City | Threshold Percent | Rain likely today? |
2 | Xian | 20 | =FORECAST_TODAY(A2,B2) |
这样我们就能获得西安当天的天气,你应该可以获得如下结果
A | B | C | |
---|---|---|---|
1 | City | Threshold Percent | Today’s Forecast |
2 | Xian | 20 | {“low”: “5”,“high”: “14”,“skycodeday”: “27”,“skytextday”: “Mostly Cloudy”,“date”: “2017-03-10”,“day”: “Friday”,“shortday”: “Fri”,“precip”: 70,“degType”: “C”,“rainLikely”: true} |
可以看到我们已经可以正常获取我们的网络请求了,rainLikely
也在precip
大于20的时候为true
,即可以判断出当天是否很有可能会下雨,大体思路也已经基本完成。
实现降雨邮件通知的功能
创建如下函数:
// 创建一个触发函数在每天指定时刻自动检查下雨几率,如果可能下雨就发送提示邮件到我们的邮箱
// 将天气预报发送至我的邮箱
function CheckForecastForRain () {
var recipient = "changjie22@qq.com"; // 指定接受邮箱,发送人自动设定为GoogleSheet用户的Gmail
var city = 'Xian';
var threshold = 20;
var today = (city, threshold);
if(today.error === undefined) {
if(today.rainLikely) {
MailApp.sendEmail({ // Google 自带的发送邮件Api
to: recipient,
subject: city + "今天有(" + today.precip + "% 几率) 可能会下雨哟! 最好随身带一把雨伞",
body: "天气预报:" + today.shortday + " " + today.low + "-" + today.high + "°" + today.degType + " " + today.skytextday + " ~ Rain: " + today.precip + "%"
});
}
}
}
在这个函数中,我们没有给他传递任何参数,因为在接下来我们要使用的项目触发器使得我们的函数在每天都会自动执行,这里不允许使用带有参数的函数,所以我们将具体信息放在了函数里面。
其中我们做了today.error === undefined
的判断,是因为forecast_today_object
函数会返回一个对象包括error
如果发生错误,这样可以使我们可以通过次来判断触发函数是否被正确执行。
我们直接使用了Google MailApp.sendEmail 方法来实现发送Email的功能,这将会自动使用你得Gmail发送一封Email。现在我们就可以测试邮件是否已可以正常发送出去。选择要执行的函数,点击Run按钮即可立即执行它。
此时你应该已经接收到了事先编好的邮件了。比如这样:
创建功能自动触发器
最后一步也非常简单,Google Sheets其实也已近内置了项目触发器,接下来我们只需设置它在比如每天早上7到8点的时候,根据当天天气是否可能下雨,自动向我们的邮箱发送通知。
在修改菜单栏中找到’当前项目的触发器’一栏。
选择需要自动触发的函数,指定在每天的上午7点至8点自动触发CheckForecastForRain
函数
这样在每天的7点到8点,我们就会根据当天的天气状况获得是否可能下雨的通知了。大功告成!!!
附其他可供使用的API:
获得当前城市的实时天气:
https://f.stdlib.com/thisdavej/weather/current/?loc=Xian°=C
UrlFetchApp.fetch 是如何实现的?
@gzhangzy 这是Google APP Script 原生的API方法,在GoogleApp上可以直接调用
我也用asyns-await写了一个[asyns-await天气查询]https://github.com/wang-weifeng/weather-api-promise-async-await
@Nicksapp 我就是问那个原生方法应该怎么实现,其它内容就没什么意思了。
@gzhangzy 本质就是一个HTTP的GET请求,可以用Ajax同样实现
@Nicksapp 不谈本质,都会。就说说怎么能形式上一模一样实现?一个异步调用,能形式上用return返回。
赞, 生命在于折腾
@gzhangzy 我怀疑那是个阻塞调用哈哈
@alsotang 也许是await request…什么的哈哈
请问 天气API 你在哪里找的,谢谢了
@gzhangzy await 和 yield 都应该是显示调用的,这个地方看着像 sync 方式的 ajax 那种用法
很有帮助
@alsotang 要是同步调用,那就没劲了。
学习了
UrlFetchApp.fetch(url)方法是异步调用吗?为什么能以同步的形式返回回来?