接氣象局api、跨網域ajax資料

接氣象局api、跨網域get資料

本篇要解決的問題

最近遇到了一個需求,就是要能夠在進入頁面時,看到天氣的預報。

查了一下,氣象局的文件說明得很簡單,就是get的url上填token跟要的資料id就行,一些google到的教學文也都是類似方式。

可是這些教學文沒說的是,get來的資料,不會是從氣象局的domain來的,一定是要跨網域請求,因此就會在console看到以下畫面:

傳說中的 No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
傳說中的 No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

本篇想解決的問題,就是如何能處理跨網域get,真正的取得氣象局api來的資料。


接氣象局api需要的3個東西

  1. 氣象局提供的授權碼
  2. 取得要get的url
  3. 可跨網域取得資料的api

1 氣象局提供的授權碼

進到氣象局的「開發指南」頁面後,會看到以下畫面:

氣象局開發指南頁面,未登入會員
氣象局開發指南頁面,未登入會員

只要註冊成為會員並登入後,就會看到「您的授權碼需登入會員後始可取得」變成「取得授權碼」的按鈕:

氣象局開發指南頁面,登入會員後
氣象局開發指南頁面,登入會員後

按下去就可以取得授權碼了,這授權碼先存起來,之後get的url會用到。

2 取得要get的url

要取得url,氣象局有提供生成器:中央氣象局開放資料平臺之資料擷取API

比方想要取台北市天氣的預報資料,就點選「鄉鎮天氣預報-臺北市未來2天天氣預報」,會看到以下:

鄉鎮天氣預報-臺北市未來2天天氣預報
鄉鎮天氣預報-臺北市未來2天天氣預報

點右側的「Try it out」,就會看見下面的說明變成一個個的填充題:

氣象局api的input生成url
氣象局api的input生成url

填完、選完這些項目後,再按下底部的「Execute」,就會產生結果預覽跟要get的url:

按下底部的「Execute」
按下底部的「Execute」
最後產生的request URL
最後產生的request URL

拿request URL去get,就可以取得所要的資料。

補充:只想取得某個區的資料

地區直接用台北市的話,就會回傳整個台北市的天氣資料,但如果只想要某個區呢?比方說信義區?

只要在填寫時,loactionName那邊填寫要的區就行了,如圖:

locationName填寫只要get的區
locationName填寫只要get的區

這樣回傳的值就只會有信義區的資料。

想跨網域取得氣象局的資料,前2樣有了,最後一項就是建一個可以跨網域取得資料的api,以下開始筆記自己的撞牆之旅XD~


跨網域get資料

要取得跨網域的資料,google了很多種方法,比較常見的是jsonp,但用js試了又試,就是一直看到console報錯,因為跨網域問題所以資料進不來。

這邊提供2種方法:

  1. 直接用別人寫好的線上功能
  2. 自己寫一個後端api,用api去取資料

1 直接用別人寫好的線上功能

這線上功能的名字叫「JSON 2 JSONP」:https://json2jsonp.com/

提供的code是這樣:

https://json2jsonp.com/?url=http://domain.com/some/json&callback=cbfunc

把url後面的值換成氣象局的request URL,callback的值換成資料進來時要用的function就行了。

用別人寫好的api很快,像JSON 2 JSONP,別人都處理好了,只需要換個url跟function的名稱就行。

缺點就是,這是別人寫的,是用別人的server,如果哪天沒經營就沒了,再如果短時間內server有問題,那server掛掉多久,你get出來的頁面也會壞多久。

如果是自己開發,又是純前端,還無法自己建一個後端的api出來,可以考慮用這套。

但如果懂一點node.js或其他後端語言,就可以選擇自己寫一支api出來。

2 自己寫一個後端api,用api去取資料

如果google一下「ajax cross domain」的話,看到的解答很多都是用php去寫,像這篇:jQuery AJAX cross domain

當然,如果找一個可以用php的主機,把找到的答案ctrl c、ctrl v,然後上傳後也是可以,就是少了自己的消化。

之前學過一點node.js,這次就想用node.js來處理。

一開始寫的code如下:

用express處理http。用request接氣象局資料。因為取資料時有一併發送要抓取的時間區間,所以也裝了body-parser,並從get改成post。

最重要的就是「cross domain config」那段,設定了header後才能跨網域請求。

寫完這段後,把程式佈署上google cloud platform上就可以執行了。

如何把node.js的程式佈到GCP上?請參考這篇:

用Google Cloud Platform(GCP)建node.js網站

原本以為佈上去後,就可以開開心心的從氣象局接資料,但問題來了,假設放在GCP上的程式,產生的網站為A網站,我實際要呈現氣象資料的網站是B網站,從B站去取A站的資料,不也是跨網域嗎?

對,所以當從B網站post出去後,又一樣看到console上寫「No ‘Access-Control-Allow-Origin’ header is present on the requested resource.」

又看到這句,傻眼了。

但好在後端這次是自己處理的,只要把B網站的網域設在白名單裡就行。

google了一下,參考了這篇:POST to express.js with ‘Access-Control-Allow-Origin’

更新了第一版寫的code後如下:

測試過後,真的除了設定的網域可以get、post,其他網域是會被禁止的。

原始碼整理在Github上,歡迎取用:

https://github.com/letswritetw/letswrite-weather-api


Summary
接氣象局api、跨網域ajax資料
Article Name
接氣象局api、跨網域ajax資料
Description
本篇大綱:本篇要解決的問題、接氣象局api需要的3個東西 -1 氣象局提供的授權碼 -2 取得要get的url -3 可跨網域取得資料的api -4 補充:只想取得某個區的資料。跨網域get資料 -1 直接用別人寫好的線上功能 -2 自己寫一個後端api,用api去取資料
Augustus
Let's Write
Let's Write
Publisher Logo
訂閱
通知
guest
0 Comments
Inline Feedbacks
看所有留言