JavaScript:APIサービスのJSONデータを取得して表示する

JavaScript:APIサービスのJSONデータを取得して表示する JavaScript

残念ながら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のブラウザ画面で 右クリック - 要素を調査… で確認)
JavaScript:APIサービスのJSONデータを取得して表示する

クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、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

<?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です)

プログラム全体です。

ご自身のドメインにアップロードして実行する場合は、必ず前述のクロスドメイン対策2(PHPプログラムを介してJSONデータを得る)を完了してから実行してください。

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

コメント

タイトルとURLをコピーしました