残念ながら2020年7月31日をもって本記事で利用していたライブドアお天気サービスAPIが終了したため、以下内容は利用できなくなりました。JSONデータの取得や整形に関しては参考になりますが、プログラムは実行できませんのでご了承ください。(管理人)
この記事は、JavaScriptを使って(正確には、JavaScriptとPHPを使って)ライブドアお天気サービスAPIからJSONデータを取得し、整形して表示するということをしています。
サンプルページはこちら(動作不可)
クロスドメイン制約について
いつからなのか記憶していませんが、JavaScriptプログラムにおいてクロスドメイン制約というものが出来ました。
例えば、天気や郵便番号などのJSONデータを提供しているAPIがあったとして、今までは事前にアップロードしたJavaScriptプログラムからレスポンスを取得できました。
今現在(2018年10月現在)は、そうしたことは出来ません。
ちなみにクロスドメイン制約とは、以下の場合を指します。
クロスドメイン制約
ドメインをまたいだAPIを実行するようなJavaScriptは、ウェブブラウザが許可しない
具体的に言うと
例えば、ライブドアが提供するお天気APIは
ドメイン http://weather.livedoor.com/forecast/webservice/ 以下に存在しています。
わたしのサイト https://torisky.com/ に設置したJavaScriptプログラムからライブドアの http://weather.livedoor.com/forecast/webservice/ にあるAPIを動かすことは出来ないということです。
これをブラウザが許可していないわけです。
実際こんなエラーメッセージがでました。(FireFoxのブラウザ画面で 右クリック - 要素を調査… で確認)

クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、http://weather.livedoor.com/forecast/webservice/json/v1?city=080010 にあるリモートリソースの読み込みは拒否されます (理由: CORS ヘッダー ‘Access-Control-Allow-Origin’ が足りない)。
クロスドメイン対策1(.htaccess)
クロスドメイン対策として、受け取るヘッダー部分に Access-Control-Allow-Origin: * を追加するというものがあります。
.htaccessというファイルをJavaScriptプログラムを使用しているファイルと同じフォルダに作り
Header set Access-Control-Allow-Origin "*"
と書き込んでからJavaScriptファイルが存在するフォルダにアップロードしておきます。
しかし、わたしはこの方法でうまくいきませんでした。
もう一つの方法を示します。
クロスドメイン対策2(PHPプログラムを介してJSONデータを得る)
わたしは、.htaccessによる方法がうまくいかなかったので、APIにアクセスするためのPHPプログラムをアップしておいて、PHPプログラムを介してAPIにアクセスして、JSONレスポンスを得るという方法をとりました。
といってもこちらのサイトを参考にしたので、引用しておきます。
Livedoor の お天気Webサービス API は、JSON のテストするのに重宝しています。http://ginpro.winofsql.jp/article/419510275.html
上記サイトを参考にして実際に自分のドメインにアップロードしたPHPプログラム(PHPプログラムの中でAccess-Control-Allow-Origin: *を追加してレスポンスを返しています)
必ずJavaScriptプログラムをアップロードするドメインと同じドメインにアップロードしてください。
13行目のURLはライブドアお天気APIですが、URLを変更すれば他のJSONサービスのURLでも動作すると思います。
getLWWS.php
3 | header( "Content-Type: application/json; Charset=utf-8" ); |
4 | header( "pragma: no-cache" ); |
5 | header( "Expires: Wed, 9 Feb 2100 14:59:58 GMT" ); |
6 | header( "Cache-control: no-cache" ); |
7 | header( "Access-Control-Allow-Origin: *" ); |
9 | if ( $_GET [ 'city' ] == '' ) { |
10 | $_GET [ 'city' ] = "270000" ; |
13 | $work = file_get_contents ( "http://weather.livedoor.com/forecast/webservice/json/v1?city={$_GET['city']}" ); |
14 | $obj = json_decode( $work ); |
15 | $work = json_encode( $obj , JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ); |
ライブドアお天気APIサービスのJSONデータを取得して表示する(結論)
上記PHPプログラムをJavaScriptから利用した場合のサンプルです。
ライブドアお天気APIサービスのJSONデータを取得して表示する
今回のサンプルはあえて地区名称、今日、明日、明後日の全ての天気データと天気アイコン、最高気温、最低気温、天気概況と取得できるものほとんどを取得してみました。
必要に応じてJavaScript部分のプログラムをいじって使ってください。
JavaScript部分の8行目
var cityId = “080010“;
は都市のID番号です。変更してお使い下さい。(サンプルでは水戸市の地区id)こちらの全国地点定義表にアクセスしソースコードを開き(Ctrl+U)地区idで確認できます。(東京都なら130010です)
プログラム全体です。
ご自身のドメインにアップロードして実行する場合は、必ず前述のクロスドメイン対策2(PHPプログラムを介してJSONデータを得る)を完了してから実行してください。
HTML部分
index.html
6 | < title >livedoorお天気WebサービスからJSONデータを取得する</ title > |
7 | < link rel = "stylesheet" type = "text/css" href = "mystyle.css" > |
8 | < script src = "myWeather.js" ></ script > |
12 | < h1 >livedoorお天気WebサービスからJSONデータを取得する</ h1 > |
13 | < div id = "result" >Getting weather...</ div > |
CSS部分
style.css
6 | font-family : '游ゴシック' , 'メイリオ' , Osaka; |
9 | border-bottom : solid 1px #000 ; |
12 | border-collapse : collapse ; |
15 | border : solid 1px #000 ; |
JavaScript部分
myWeather.js
10 | var httpObj = new XMLHttpRequest(); |
12 | httpObj.open( "GET" , "https://torisky.com/libs/getLWWS.php?city=" + cityId, true ); |
14 | httpObj.onload = function (){ |
15 | data = JSON.parse( this .responseText); |
17 | console.log( "XHR送信成功!!" ); |
23 | function showWeather(data){ |
25 | tag += "<h2>" + data.location.city + "の天気</h2>" ; |
27 | tag += "<tr><th>日付</th><th>天気</th><th>最高気温</th><th>最低気温</th></tr>" ; |
29 | for ( var i in data.forecasts){ |
32 | tag += "<td>" + data.forecasts[i].dateLabel + data.forecasts[i].date + "</td>" ; |
34 | tag += "<td><img src='" + data.forecasts[i].image.url + "' width='50' height='31'>" + data.forecasts[i].telop + "</td>" ; |
36 | var max = data.forecasts[i].temperature.max; |
38 | tag += "<td class='center'>" ; |
39 | if (max.celsius >= 30){ |
40 | tag += "<span class='red'>" + max.celsius + "℃</span>" ; |
43 | tag += max.celsius + "℃" ; |
48 | tag += "<td class='center'>-</td>" ; |
51 | var min = data.forecasts[i].temperature.min; |
53 | tag += "<td class='center'>" ; |
55 | tag += "<span class='blue'>" + min.celsius + "℃</span>" ; |
58 | tag += min.celsius + "℃" ; |
63 | tag += "<td class='center'>-</td>" ; |
70 | var d = new Date(data.publicTime); |
71 | var month = d.getMonth() + 1; |
72 | var date = d.getDate(); |
73 | var hour = d.getHours(); |
74 | var minute = d.getMinutes(); |
75 | tag += "<p class='description'>" + month + "/" + date + " " + hour + "時 発表</p>" ; |
77 | tag += "<p class='description'>" + data.description.text + "</p>" ; |
79 | result.innerHTML = tag; |
82 | window.onload = function (){ |
83 | result = document.getElementById( "result" ); |
ライブドアお天気APIサービスのJSONデータ注意点
ライブドアお天気APIサービスのJSONデータの注意点として、時間帯によっては、最高気温や最低気温がなかったり、明後日の天気データが提供されていなかったりすることがあります。
わたしは今日、明日、明後日の最高気温と最低気温が必ずJSONデータとして返される情報として考えていましたが、違っていました。時間帯によって最高気温や最低気温がない場合があります。
やっかいなことにnullが返されてしまうので対策が必要でした。
今回は、
if(max != null){ // データが存在しているときの処理 }
などとしてチェックしています。
どうやら明日の天気データに関しては、常に最高気温と最低気温が存在しているようです。
ライブドアお天気サービスWeb仕様に関しては以下を参考にしてください。
http://weather.livedoor.com/weather_hacks/webservice
コメント