残念ながら2020年7月31日をもって本記事で利用していたライブドアお天気サービスAPIが終了したため、以下内容は利用できなくなりました。JSONデータの取得や整形に関しては参考になりますが、プログラムは実行できませんのでご了承ください。(管理人)
この記事は、JavaScriptを使って(正確には、JavaScriptとPHPを使って)ライブドアお天気サービスAPIからJSONデータを取得し、整形して表示するということをしています。
サンプルページはこちら(動作不可)
クロスドメイン制約について
いつからなのか記憶していませんが、JavaScriptプログラムにおいてクロスドメイン制約というものが出来ました。
例えば、天気や郵便番号などのJSONデータを提供しているAPIがあったとして、今までは事前にアップロードしたJavaScriptプログラムからレスポンスを取得できました。
今現在(2018年10月現在)は、そうしたことは出来ません。
ちなみにクロスドメイン制約とは、以下の場合を指します。
クロスドメイン制約
具体的に言うと
ドメイン http://weather.livedoor.com/forecast/webservice/ 以下に存在しています。
わたしのサイト https://torisky.com/ に設置したJavaScriptプログラムからライブドアの http://weather.livedoor.com/forecast/webservice/ にあるAPIを動かすことは出来ないということです。
これをブラウザが許可していないわけです。
実際こんなエラーメッセージがでました。(FireFoxのブラウザ画面で 右クリック - 要素を調査… で確認)
クロスドメイン対策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: *を追加してレスポンスを返しています)
13行目のURLはライブドアお天気APIですが、URLを変更すれば他のJSONサービスのURLでも動作すると思います。
getLWWS.php
<?php // http://ginpro.winofsql.jp/article/419510275.htmlより引用 header( "Content-Type: application/json; Charset=utf-8" ); header( "pragma: no-cache" ); header( "Expires: Wed, 9 Feb 2100 14:59:58 GMT" ); header( "Cache-control: no-cache" ); header( "Access-Control-Allow-Origin: *" ); if ( $_GET['city'] == '' ) { $_GET['city'] = "270000"; } $work = file_get_contents( "http://weather.livedoor.com/forecast/webservice/json/v1?city={$_GET['city']}" ); $obj = json_decode( $work ); $work = json_encode( $obj, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ); print $work; ?>
ライブドアお天気APIサービスのJSONデータを取得して表示する(結論)
上記PHPプログラムをJavaScriptから利用した場合のサンプルです。
ライブドアお天気APIサービスのJSONデータを取得して表示する
今回のサンプルはあえて地区名称、今日、明日、明後日の全ての天気データと天気アイコン、最高気温、最低気温、天気概況と取得できるものほとんどを取得してみました。
必要に応じてJavaScript部分のプログラムをいじって使ってください。
JavaScript部分の8行目
var cityId = “080010“;
は都市のID番号です。変更してお使い下さい。(サンプルでは水戸市の地区id)こちらの全国地点定義表にアクセスしソースコードを開き(Ctrl+U)地区idで確認できます。(東京都なら130010です)
プログラム全体です。
HTML部分
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>livedoorお天気WebサービスからJSONデータを取得する</title> <link rel="stylesheet" type="text/css" href="mystyle.css"> <script src="myWeather.js"></script> </head> <body> <h1>livedoorお天気WebサービスからJSONデータを取得する</h1> <div id="result">Getting weather...</div> </body> </html>
CSS部分
style.css
/* mystyle.css */ body{ margin: 50px; padding: 0; background: #fff; font-family: '游ゴシック', 'メイリオ', Osaka; } h1{ border-bottom: solid 1px #000; } table{ border-collapse: collapse; } table, th, td{ border: solid 1px #000; } th, td{ padding: 0.5em; } #result{ font-size:24px; } .description{ font-size: 16px; } .center{ text-align: center; } .red{ color: red; } .blue{ color: blue; }
JavaScript部分
myWeather.js
/* * myWeather.js: livedoorお天気WebサービスからJSONデータを取得する */ // 取得する地域 var result = null; var data = null; var cityId = "080010"; var httpObj = new XMLHttpRequest(); // 事前にアップしたPHPプログラムを介して、livedoorお天気WebサービスからJSONデータ取得する httpObj.open("GET", "https://torisky.com/libs/getLWWS.php?city=" + cityId, true); httpObj.onload = function(){ data = JSON.parse(this.responseText); // JSON形式データを変換 console.log(data); console.log("XHR送信成功!!"); showWeather(data); } httpObj.send(null); function showWeather(data){ var tag = ""; tag += "<h2>" + data.location.city + "の天気</h2>"; tag += "<table>"; tag += "<tr><th>日付</th><th>天気</th><th>最高気温</th><th>最低気温</th></tr>"; for(var i in data.forecasts){ // 天気情報取得(i = 0:今日、i = 1: 明日、i = 2:あさって) tag += "<tr>"; // 「今日」「明日」「明後日」+ 日付 tag += "<td>" + data.forecasts[i].dateLabel + data.forecasts[i].date + "</td>"; // 天気アイコン画像+天気の文字(例:晴れ) tag += "<td><img src='" + data.forecasts[i].image.url + "' width='50' height='31'>" + data.forecasts[i].telop + "</td>"; // 最高気温(データがnullの場合がある) var max = data.forecasts[i].temperature.max; if(max != null){ tag += "<td class='center'>"; if(max.celsius >= 30){ tag += "<span class='red'>" + max.celsius + "℃</span>"; } else{ tag += max.celsius + "℃"; } tag += "</td>"; } else{ tag += "<td class='center'>-</td>"; } // 最低気温(データがnullの場合がある) var min = data.forecasts[i].temperature.min; if(min != null){ tag += "<td class='center'>"; if(min.celsius <= 5){ tag += "<span class='blue'>" + min.celsius + "℃</span>"; } else{ tag += min.celsius +"℃"; } tag += "</td>"; } else{ tag += "<td class='center'>-</td>"; } tag += "</tr>"; } tag += "</table>"; // 日付を整形 var d = new Date(data.publicTime); var month = d.getMonth() + 1; var date = d.getDate(); var hour = d.getHours(); var minute = d.getMinutes(); tag += "<p class='description'>" + month + "/" + date + " " + hour + "時 発表</p>"; // 天気概況 tag += "<p class='description'>" + data.description.text + "</p>"; result.innerHTML = tag; } window.onload = function(){ result = document.getElementById("result"); }
ライブドアお天気APIサービスのJSONデータ注意点
ライブドアお天気APIサービスのJSONデータの注意点として、時間帯によっては、最高気温や最低気温がなかったり、明後日の天気データが提供されていなかったりすることがあります。
わたしは今日、明日、明後日の最高気温と最低気温が必ずJSONデータとして返される情報として考えていましたが、違っていました。時間帯によって最高気温や最低気温がない場合があります。
やっかいなことにnullが返されてしまうので対策が必要でした。
今回は、
if(max != null){ // データが存在しているときの処理 }
などとしてチェックしています。
どうやら明日の天気データに関しては、常に最高気温と最低気温が存在しているようです。
ライブドアお天気サービスWeb仕様に関しては以下を参考にしてください。http://weather.livedoor.com/weather_hacks/webservice
コメント