上一篇我們了解中央氣象局API取得的方法了。
再來我們來想想使用者會想要怎麼跟機器人溝通來取得天氣資料。
其實做法有好幾種。
可以分好幾層,先跟機器人說要查天氣,機器人問說要查甚麼時間,回覆時間,要查哪裡的天氣,回覆地點……。
又或者說可以用Inline keyboard來讓使用者選擇要查的時間地點等等。
說真的我覺得使用者應該會想要馬上查到想要的資料,不會想要慢慢一個一個訊息傳給機器人後才得到資訊。
所以我的設計是只要輸入/weather 地點,就可以顯示出那個地點的未來36hr天氣預報。
首先我一樣在sendtext方法寫了一個message的判斷式。
if(estringa.message.text.match("/weather ")){
var temp = estringa.message.text.split("/weather ");
var location = temp[1];
var Weatherfile = get_weather(location,chatid);
var mensaje = weather_forecast(Weatherfile,location,chatid);
return mensaje;
}
第1行:判斷訊息是否符合/weather
,這邊要特別注意,/weather
的後面是有一個空格的。
第2行:把/weather <城市>
,整段訊息分兩部分拆開,temp[0]
是/weather
,temp[1]
是<城市>。
第3行:將城市名稱放入location
。
第4行:將get_weather
的資料放入Weatherfile
第5行:將Weatherfile
放入weather_forecast
方法並執行。
關於文字的判斷,如何去避免使用者只輸入/weather
後面沒輸入城市,或是輸入沒有的城市等等的狀況,我就不特別說明了,寫法有很多種大家可以自行發揮。
另外開一個指令碼專案,名稱設為weather.gs
裡面包含兩個方法:get_weather
、weather_forecast
function get_weather(location,chatid){
var response = UrlFetchApp.fetch("https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=你的授權碼" + "&" + "locationName=" + location );
var weatherData = JSON.parse(response);
//Logger.log(response);
return weatherData;
}
第1行:把location
跟chatid
放入get_weather
方法,這邊要注意,()
裡面放的參數要和sendtext
方法裡面寫的一樣。
第3行:fetch至中央氣象局的API資料,location
為前面使用者在輸入/weather <城市>
,時所打的地點。
第4行:將response
的資料轉為JSON格式儲存。
第5行:設一個Log
用來測試是否有取得API資料。
第6行:這邊要記得是return weatherData
而不是return response
,因為如果沒有返回weatherData
,那得到的資料就不會是JSON格式,在後面取得資料時就會出錯。
function weather_forecast(Weatherfile,location,chatid) {
var payload = {
"method": "sendMessage",
'chat_id': "chatid",
'text': '測試傳送天氣預報'
}
payload.text = location+ " 36hr天氣預報\n" + "\n" +
Weatherfile.records.location[0].weatherElement[0].time[0].startTime+ "~" + Weatherfile.records.location[0].weatherElement[0].time[0].endTime +"\n"+
"天氣狀態:"+ Weatherfile.records.location[0].weatherElement[0].time[0].parameter.parameterName+ "\n" +
"降雨機率:"+ Weatherfile.records.location[0].weatherElement[1].time[0].parameter.parameterName+ "%" + "\n" +
"最低溫度:"+ Weatherfile.records.location[0].weatherElement[2].time[0].parameter.parameterName+ "°C" + "\n" +
"最高溫度:"+ Weatherfile.records.location[0].weatherElement[4].time[0].parameter.parameterName+ "°C" + "\n" +
"天氣舒適度:"+ Weatherfile.records.location[0].weatherElement[3].time[0].parameter.parameterName+ "\n" + "\n" +
Weatherfile.records.location[0].weatherElement[0].time[1].startTime+ "~" + Weatherfile.records.location[0].weatherElement[0].time[1].endTime +"\n"+
"天氣狀態:"+ Weatherfile.records.location[0].weatherElement[0].time[1].parameter.parameterName+ "\n" +
"降雨機率:"+ Weatherfile.records.location[0].weatherElement[1].time[1].parameter.parameterName+ "%" + "\n" +
"最低溫度:"+ Weatherfile.records.location[0].weatherElement[2].time[1].parameter.parameterName+ "°C" + "\n" +
"最高溫度:"+ Weatherfile.records.location[0].weatherElement[4].time[1].parameter.parameterName+ "°C" + "\n" +
"天氣舒適度:"+ Weatherfile.records.location[0].weatherElement[3].time[1].parameter.parameterName+ "\n" + "\n" +
Weatherfile.records.location[0].weatherElement[0].time[2].startTime+ "~" + Weatherfile.records.location[0].weatherElement[0].time[2].endTime +"\n"+
"天氣狀態:"+ Weatherfile.records.location[0].weatherElement[0].time[2].parameter.parameterName+ "\n" +
"降雨機率:"+ Weatherfile.records.location[0].weatherElement[1].time[2].parameter.parameterName+ "%" +"\n"+
"最低溫度:"+ Weatherfile.records.location[0].weatherElement[2].time[2].parameter.parameterName+ "°C" + "\n" +
"最高溫度:"+ Weatherfile.records.location[0].weatherElement[4].time[2].parameter.parameterName+ "°C" + "\n" +
"天氣舒適度:"+ Weatherfile.records.location[0].weatherElement[3].time[2].parameter.parameterName+ "\n" +"";
//Logger.log(payload.text);
return payload;
}
這邊其實就只要搞懂我們API JSON格式的內容就很容易懂了。
在前面我們已經把get_weather
方法的資料全部放進Weatherfile
了,也就是說Weatherfile
就是我們抓到JSON格式的資料。
我們檢視JSON的內容會看到裡面分了好幾層,而我們要抓的資料必須要一層一層抽出來。
最外層的部分是records
物件。
再來是location
陣列,location
陣列第一個值location[0]
是新北市
再來是weatherElement
陣列,weatherElement[0]
是elementName:Wx
天氣狀況,weatherElement[1]
是elementName:PoP
降雨機率。
再來是time陣
列,time
陣列分成三個時段,time[0]
,time[1]
,time[2]
。
再來是parameter
物件,裡面包含parameterName
跟parameterValue
兩個值。
可以看到我在上面的敘述裡面特別強調物件還有陣列,這是因為如果是物件的話則不需要在後面加上[]
來指定要取的值,如果是陣列的話則一定要加,我就在parameter
的地方加上[]
而一直出錯,直到後來才發現他不是陣列,抓資料時在數據的型態這部分一定要特別注意。
講到這邊大家應該有點概念了,假設我想要抓第一個時間段的值,我就把時間設為time[0]
,如果要抓某種天氣因子,就把weatherElement
設為想要抓的天氣因子。
透過不同的排列組合就可以抓出想要的資料,像上方我寫的方法抓出來的資料就會長這樣。
那最後在GAS測試完記得部屬,到機器人這邊輸入訊息測試結果,實作完的成果就會是這樣。
這個天氣機器人的功能其實也跟以圖搜圖一樣,是最初就想要做到的。
在做這個天氣機器人時其實也遇到了許多問題,基本上分三個問題吧。
我在做這個之前,根本就沒有抓過API,只對這種資料擷取的方式有點概念,所以在寫如何抓API資料的時候,其實有點靠運氣。
在看資料時發現中央氣象局的API資料取得時就已經是JSON格式了,就想說照著前一篇以圖搜圖的方法試著寫寫看,也不確定這樣子的寫法是不是對的,試著試著居然就寫出來了。
這次遇到的問題還有在return的地方回傳錯誤的值,一時也沒有發現,就這樣整個半天都卡在這邊,大家要記得加上return傳回自己前面放的值,也要記得參數別放錯。
最後一個遇到的問題就是解析JSON資料時遇到的,這種資料要一層一層的抓出來,資料的型態一定要特別注意,可以先不要抓太大量的資料,先從小範圍的值來看,從最一開始的records慢慢往外一層一層寫,會比較好理解。
總之,只要大家懂得fetch API的方式,就可以抓想要的API資料,並且透過解析JSON格式的資料,就能抓出特定的資訊,如此不管是今明36小時的天氣預報,又或者是地震報告、紫外線指數等等資料,都可以透過這個方法來呈現。
老話一句,接下來就看各位的發揮了!
https://www.est.idv.tw/telegram-bot-function-36hr%E6%B0%A3%E8%B1%A1%E9%A0%90%E5%A0%B1/