iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 11
2
自我挑戰組

LINE BOT 新手村30日攻略系列 第 11

Day11 LINE BOT & 天氣預報 - 1

  • 分享至 

  • xImage
  •  

今日練習 Github 連結

今天終於要開始我們的實作拉~
這次要做的是未來 36 小時天氣預測資料
會利用到中央氣象局的API資料

小叮嚀
本機測試可以用 ngrok 做臨時的 wenhook
也要記得到 LINE Official Account Manager 修改 webhook 連結喔!

如何獲取資料

我們現在有中央氣象局的 API,現在只需要使用 Python 內的 requests 套件
我們要先到中央氣象局 開放資料平台辦一個帳號
接下來到會員資訊 - API授權碼 取得我們的 Token

接下來直接對 API 提供的連結 GET ,就可以拿到我們的資料了
可以參考中央氣象局的API資料
我們可以寫一個 get 的 function 去獲取資料

import requests
def get(city):
    token = 'YourToken' //這裡記得換成剛剛生成的 Token
    url = 'https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=' + token + '&format=JSON&locationName=' + str(city)
    Data = requests.get(url)
    print(Data.text)

我們可以先以 臺北市 為例,看看接收到的文字內容

{
    "success": "true",
    "result": {
        "resource_id": "F-C0032-001",
        "fields": [
            {...}
        ]
    },
    "records": {
        "datasetDescription": "三十六小時天氣預報",
        "location": [
            {
                "locationName": "臺北市",
                "weatherElement": [
                    {
                        "elementName": "Wx",
                        "time": [
                            {
                                "startTime": "2020-09-26 18:00:00",
                                "endTime": "2020-09-27 06:00:00",
                                "parameter": {
                                    "parameterName": "陰陣雨",
                                    "parameterValue": "14"
                                }
                            },
                            {...}
                        ]
                    },
                    {
                        "elementName": "PoP",
                        "time": [
                            {
                                "startTime": "2020-09-26 18:00:00",
                                "endTime": "2020-09-27 06:00:00",
                                "parameter": {
                                    "parameterName": "80",
                                    "parameterUnit": "百分比"
                                }
                            },
                            {...}
                        ]
                    },
                    {
                        "elementName": "MinT",
                        "time": [
                            {
                                "startTime": "2020-09-26 18:00:00",
                                "endTime": "2020-09-27 06:00:00",
                                "parameter": {
                                    "parameterName": "21",
                                    "parameterUnit": "C"
                                }
                            },
                            {...}
                        ]
                    },
                    {
                        "elementName": "CI",
                        "time": [
                            {
                                "startTime": "2020-09-26 18:00:00",
                                "endTime": "2020-09-27 06:00:00",
                                "parameter": {
                                    "parameterName": "舒適"
                                }
                            },
                            {...}
                        ]
                    },
                    {
                        "elementName": "MaxT",
                        "time": [
                            {
                                "startTime": "2020-09-26 18:00:00",
                                "endTime": "2020-09-27 06:00:00",
                                "parameter": {
                                    "parameterName": "23",
                                    "parameterUnit": "C"
                                }
                            },
                            {...}
                        ]
                    }
                ]
            }
        ]
    }
}

注意一下裡面的幾個參數

資料內都是以 12 小時為一個區間

另外可以發現到,我們拿到的資料會是字串型態的 JSON
可以利用 Python 的 JSON 套件將字串轉換成 dict ,方便未來存取

規劃 BOT 內容

現在我們有資料了,之前曾經提到在開發 LINE BOT 時,很重要的是 輸入輸出 的概念
我們要先決定好輸入與輸出的格式

輸入

我們希望用戶輸入 天氣 {縣市} 來要求獲取天氣資料
其中 {縣市} 要替換成縣市的名稱
例如要查詢臺北市 天氣 臺北市
因為台灣的縣市名稱有 的不同,我們直接統一將使用者輸入的台改寫成大寫的臺

輸出

針對上面我們有的資料,我希望只輸出:

  • 天氣現象
  • 最高最低溫度
  • 降雨機率

而輸出的格式會是以 Carousel 的型態輸出
且每一個 column 都代表一個 12 小時的區間
下方有個按鈕導向中央氣象局的網站
像是這樣子


好的~目前稍微規劃好了,我們先來處理輸入吧~

if(message[:2] == '天氣'):
    city = message[3:]
    city = city.replace('台','臺')
    # 使用者輸入的內容並非符合格式
    if(not (city in cities)):
        line_bot_api.reply_message(reply_token,TextSendMessage(text="查詢格式為: 天氣 縣市"))
    else:
        # 處理輸出

現在來整理一下資料吧~

我希望我可以將資料分成 3 個部分,分別表示每 12 個小時的一個區間
稍微改寫一下前面的 get function 來處理吧~

def get(city):
    token = 'YourToken'
    url = 'https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=' + token + '&format=JSON&locationName=' + str(city)
    Data = requests.get(url)
    Data = (json.loads(Data.text,encoding='utf-8'))['records']['location'][0]['weatherElement']
    res = [[] , [] , []]
    for j in range(3):
        for i in Data:
            res[j].append(i['time'][j])
    return res
  • Line 5
    我們關注的資料全部都在 ['records']['location'][0]['weatherElement']
    所以只需要留下這些即可
  • Line 6~9
    我們將 res 改寫成一個有3格的 list ,而每一格裡面都包含一個時間區段的 dict
    關於 JSON 的部分可以參考程式前沿

最後就剩下輸出了

我們主要關注在 titletext

注意到
title 最多 40 字
text 最多 60 字

title 格式為: 月-日 時:分 ~ 月-日 時:分
text 格式為: 天氣狀況 {}\n溫度 {} ~ {} °C\n降雨機率 {}

最終的輸出 code

res = get(city)
line_bot_api.reply_message(reply_token, TemplateSendMessage(
    alt_text = city + '未來 36 小時天氣預測',
    template = CarouselTemplate(
        columns = [
            CarouselColumn(
                thumbnail_image_url = 'https://i.imgur.com/Ex3Opfo.png',
                title = '{} ~ {}'.format(res[0][0]['startTime'][5:-3],res[0][0]['endTime'][5:-3]),
                text = '天氣狀況 {}\n溫度 {} ~ {} °C\n降雨機率 {}'.format(data[0]['parameter']['parameterName'],data[2]['parameter']['parameterName'],data[4]['parameter']['parameterName'],data[1]['parameter']['parameterName']),
                actions = [
                    URIAction(
                        label = '詳細內容',
                        uri = 'https://www.cwb.gov.tw/V8/C/W/County/index.html'
                    )
                ]
            )for data in res
        ]
    )
))

完整的程式碼可以參考今日練習 Github 連結

後記

經過這次的練習,大概可以學到

  1. 如何使用 API 抓取資料
  2. 如何針對獲取的資料進行處理
  3. 如何輸出 Carousel 訊息

不過這一個版本中還有很多可以改進的部分
像是對於使用者而言,每次查詢還需要輸入文字是很麻煩的
在下一篇我們會提到改良的方式

實際上到這邊,各位都有能力自己做出一個 LINE BOT
各式的訊息 接收/傳送 都已經在前面完整說明過
大概最後遇到的幾乎都不會是 LINE BOT API 的使用問題ww
大概最頭痛的會是資料處理的部分
透過這次實作應該也能發現到我們花了不少時間在處理資料

另外,這次也強調將特定的功能另外拉出來寫成一個 function
這在未來對於開發專案是很有幫助的
先在 main 裡面寫好邏輯,預先設定該函數回傳的內容
這樣一來在寫程式上會輕鬆需多,一次只需要注意一件事即可

接下來極有可能會是每天都帶實作
這真的有點可怕QQ
希望各位客官如果任何想法或是建議
例如希望我嘗試做做看什麼功能w
都歡迎在下面留言喔~

參考資料

中央氣象局 - 開放資料平台
中央氣象局 - 預報XML產品預報因子欄位中文說明表
中央氣象局 API線上說明文件
程式前沿


上一篇
Day10 進階訊息傳送4 - Imagemap Message
下一篇
Day12 LINE BOT & 天氣預報 - 2
系列文
LINE BOT 新手村30日攻略30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言