残念ながら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
コメント