自從2024年4月3日的花蓮大地震發生之後,隨之而來的大小餘震便不斷的侵擾著大家的安寧生活。
尤其是三不五時就突如其來的一震,除了驚嚇之外,也增加了不少精神壓力,以及對所處環境的疑慮,甚至引發了不少「幻覺地震」的情況。
每當疑似地震發生後,心裡總會開始著急的想關心,剛才所遭遇的究竟是現實,還是因為連續數天的緊張所導致的妄想。
此時,看著桌上那面平時負責提醒我待辦事項的「人工智障」,我便萌生了讓她擔任地震播報員的構想。
是時候,讓她變得更有用了。
首先,若要建立這種即時訊息播報模組,一切的根本就是要找到一個更新快速,同時又可靠的資料來源。
而這裡我們要使用的是由中央氣象署的氣象資料開放平台所提供的 API 來取得所需的即時地震資料,接下來也會說明如何取得與使用。
想要取用這裡的 API 的話,就要先註冊一組會員帳號,不過註冊過程需要填寫的內容不多,僅需 Email 與 密碼 即可。
因此這裡就快速的註冊一組,下方訂閱的部分可全部留空,不會影響後續流程。
完成註冊後,會在帳號信箱中收到一封驗證信,記得先去做驗證之後再回來登入,接著就會被帶到這個取得授權碼的畫面。
在這裡直接按下【取得授權碼】後,就會直接在按鈕旁看到自己的授權碼了。
要注意的是,這組授權碼就是你要從 API 取回資料的憑證,請小心保管以免被濫用。
以上,註冊步驟就大致完成了,接著就可以準備來串接資料啦。
這次模組的主要功能,是要進行第震訊息的即時播報,因此在【資料主題】中就要選擇「地震海嘯」這個項目。
進到資料列表後,可以看到在地震海嘯主題中有不少子項目,而其中有提供 API 的資料中,我們選擇「顯著有感地震報告資料-顯著有感地震報告」這一項作為主要訊息來源。
點進去後,就可以看到表格最上方大大的【API】字樣,那個就是這次的目標啦。
註:這個項目要登入後才會顯示喔。
不過在開始寫程式取用資料之前,我們還要先來看一下可以取得的內容,這裡直接點進【API】連結,系統便會帶我們來到一個神祕的測試區域來。
這個頁面可以在正式開發前,先對我們所想要從 API 取得的資料進行參數的調整,也就是說透過這些選項,由他們的伺服器預先篩好資料
這樣我們就可以省去在處理的步驟,按下右上角的【Try It Out】就可以開始調整測試。
其實在官方 API 中大部份可用的參數,在這個頁面中都有做說明,可以自行參考後再進行調整,這裡我就只列出我有額外做設定的幾個項目。
調整完畢,接著按下最下方的【Execute】後,就可以看到回傳資料的預覽了。
回傳預覽如下
另外,在上方還會列出取得資料用的 Curl 指令以及 Request 網址,如果已經確認參數的話,就可以直接先將 Request 這部分複製下來備用。
接著就是讓人臉紅心跳,興奮期待的爬蟲時間啦。(並沒有
以上,我們已經拿到了抓取資料的 URL 連結,接著就是來用程式化的方式來自動取得最新警報啦。
這裡同樣的請到老朋友 Python 來坐鎮,所需用到的是「requests」這個套件來做爬蟲資料抓取,那就不囉嗦,直接上程式碼囉。
import requests
# Replace With Your Auth key
API_Key = "YOUR_API_KEY"
# Request URL Copied From Last Step
api = "https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001?Authorization="+API_Key+"&limit=1&format=JSON&AreaName="
# Get JSON Data from URL With Requests Package
r = requests.get(api,headers={'Accept': 'application/json'})
jdata = r.json()
看起來很簡單對吧!
其實邏輯也不難,因為這裡所獲得的資料已經是伺服器端幫我們整理好格式化的,因此省去許多處理骯髒資料的步驟,我們只要再從抓回來的內容中,再細篩出我們要的內容就好了。
上面的範例中,唯獨要注意的部分是,我把授權碼從 URL 中切出來,放在另一個變數中了,這樣做的好處是之後如果因為某些原因要重新生成授權碼的話,可以直接修改 「API_KEY」這個變數內容就好。
甚至更安全的做法,就是將授權從程式碼中移除,直接用 Config 或是 系統變數 的方式儲存,可以避免授權被攔截盜用。
接著我們先在 Jupyter Notebook 中測試執行上面的程式,看一下回傳的資料,可以發現在內容上大致就跟網頁上測試時的相同。
由於我這個模組最終是會使用文字轉語音自動朗讀的,因此就只取發生時間、主要震央位置,以及最大震度這一項資訊,如果從 Json 中細篩的話,階層大概是
jdata['records']['Earthquake'][0]['ReportContent']
而實際抓出來的內容就會像是這樣。
到這裡我們這次的目的大致上已經達成了,但如果想要有比較順暢的文字語音的話,可以在針對這串文字做內容調整,讓語句更自然通順。
到目前為止,我們已經能順利抓到我們要的資訊了。
不過,既然我們要做的是即時播報的功能,就勢必得讓爬蟲能夠持續運作,並定時抓取最新訊息,因此接下來所要做的,就是讓它能夠自動化的執行下去。
而提到循環運作,相信有一些程式概念的人,應該都會想到「迴圈」這個詞吧?
沒錯,這裡就是要使用迴圈的特性來讓爬蟲能夠定時處理資料擷取的工作。
以我自己的「人工智障」專案來說,就可以綁在控制電子紙螢幕的主程式中一起執行。
不過,為了大家提供參考,這裡就另外做一份簡化後的範例吧!
import requests
import time
# Replace With Your Auth key
API_Key = "YOUR_API_KEY"
# Function to Get Request Data
def getquk():
# Request URL Copied From Last Step
api = "https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001?Authorization="+API_Key+"&limit=1&format=JSON&AreaName="
# Get JSON Data from URL With Requests Package
r = requests.get(api,headers={'Accept': 'application/json'})
jdata = r.json()
# Get Content
res = jdata['records']['Earthquake'][0]['ReportContent']
return res
# Info Buffer
buff = None
# Main Loop
while True:
# Get Latest Earthquake Info
qdata = getquk()
# If Any New Alert
if qdata != buff:
# Put TTS System Here
print(qdata)
# Update Buffer
buff = qdata
# Wait 100 Sec For Next Loop
time.sleep(100)
嗯⋯事情看起來有點複雜了。
簡而言之,就是將前面的爬蟲步驟定義成一個名為「getquk」的功能,並且每 100 呼叫一次來取得最新資訊。
而每一次所拿到的資料,都會先跟一組暫存的紀錄作比對,如果有任何變化,就會觸發特定動作,而這個動作就可以是呼叫額外的文字轉語音模組把最新資訊朗讀出來。
最後再將暫存紀錄做更新,然後進入待命 100 秒後,再重新執行一次,直到程式終止。
以上,就是這次的地震播報模組開發紀錄啦。
在我寫完這個模組,並實裝在實際硬體設備上後,當天下午就連續收到兩次的通報,有一次還是確實有感,仔細想想也是真的蠻嚇人的。
近期餘震仍頻繁,再加上部分區域又開始變天下雨,也希望大家都能平安度過囉。
《計畫。待續》