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

1<?php
2// http://ginpro.winofsql.jp/article/419510275.htmlより引用
3header( "Content-Type: application/json; Charset=utf-8" );
4header( "pragma: no-cache" );
5header( "Expires: Wed, 9 Feb 2100 14:59:58 GMT" );
6header( "Cache-control: no-cache" );
7header( "Access-Control-Allow-Origin: *" );
8 
9if ( $_GET['city'] == '' ) {
10    $_GET['city'] = "270000";
11}
12 
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 );
16 
17print $work;
18?>

ライブドアお天気APIサービスのJSONデータを取得して表示する(結論)

上記PHPプログラムをJavaScriptから利用した場合のサンプルです。

ライブドアお天気APIサービスのJSONデータを取得して表示する

今回のサンプルはあえて地区名称、今日、明日、明後日の全ての天気データと天気アイコン、最高気温、最低気温、天気概況と取得できるものほとんどを取得してみました。
必要に応じてJavaScript部分のプログラムをいじって使ってください。

JavaScript部分の8行目

var cityId = “080010“;

は都市のID番号です。変更してお使い下さい。(サンプルでは水戸市の地区id)こちら全国地点定義表にアクセスしソースコードを開き(Ctrl+U)地区idで確認できます。(東京都なら130010です)

プログラム全体です。

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

HTML部分

index.html

1<!DOCTYPE html>
2<html>
3 
4<head>
5    <meta charset="utf-8">
6    <title>livedoorお天気WebサービスからJSONデータを取得する</title>
7    <link rel="stylesheet" type="text/css" href="mystyle.css">
8    <script src="myWeather.js"></script>
9</head>
10 
11<body>
12    <h1>livedoorお天気WebサービスからJSONデータを取得する</h1>
13    <div id="result">Getting weather...</div>
14</body>
15 
16</html>

CSS部分

style.css

1/* mystyle.css */
2body{
3    margin: 50px;
4    padding: 0;
5    background: #fff;
6    font-family: '游ゴシック', 'メイリオ', Osaka;
7}
8h1{
9    border-bottom: solid 1px #000;
10}
11table{
12    border-collapse: collapse;
13}
14table, th, td{
15    border: solid 1px #000;
16}
17th, td{
18    padding: 0.5em;
19}
20#result{
21    font-size:24px;
22}
23.description{
24    font-size: 16px;
25}
26.center{
27    text-align: center;
28}
29.red{
30    color: red;
31}
32.blue{
33    color: blue;
34}

JavaScript部分

myWeather.js

1/*
2 * myWeather.js: livedoorお天気WebサービスからJSONデータを取得する
3 */
4 
5// 取得する地域
6var result = null;
7var data = null;
8var cityId = "080010";
9 
10var httpObj = new XMLHttpRequest();
11// 事前にアップしたPHPプログラムを介して、livedoorお天気WebサービスからJSONデータ取得する
12httpObj.open("GET", "https://torisky.com/libs/getLWWS.php?city=" + cityId, true);
13 
14httpObj.onload = function(){
15    data = JSON.parse(this.responseText);   // JSON形式データを変換
16    console.log(data);
17    console.log("XHR送信成功!!");
18    showWeather(data);
19}
20 
21httpObj.send(null);
22 
23function showWeather(data){
24    var tag = "";
25    tag += "<h2>" + data.location.city + "の天気</h2>";
26    tag += "<table>";
27    tag += "<tr><th>日付</th><th>天気</th><th>最高気温</th><th>最低気温</th></tr>";
28 
29    for(var i in data.forecasts){   // 天気情報取得(i = 0:今日、i = 1: 明日、i = 2:あさって)
30        tag += "<tr>";
31        // 「今日」「明日」「明後日」+ 日付
32        tag += "<td>" + data.forecasts[i].dateLabel + data.forecasts[i].date + "</td>";
33        // 天気アイコン画像+天気の文字(例:晴れ)
34        tag += "<td><img src='" + data.forecasts[i].image.url + "' width='50' height='31'>" + data.forecasts[i].telop + "</td>";
35        // 最高気温(データがnullの場合がある)
36        var max = data.forecasts[i].temperature.max;
37        if(max != null){
38            tag += "<td class='center'>";
39            if(max.celsius >= 30){
40                tag += "<span class='red'>" + max.celsius + "℃</span>";
41            }
42            else{
43                tag += max.celsius + "℃";
44            }
45            tag += "</td>";
46        }
47        else{
48            tag += "<td class='center'>-</td>";
49        }
50        // 最低気温(データがnullの場合がある)
51        var min = data.forecasts[i].temperature.min;
52        if(min != null){
53            tag += "<td class='center'>";
54            if(min.celsius <= 5){
55                tag += "<span class='blue'>" + min.celsius + "℃</span>";
56            }
57            else{
58                tag += min.celsius +"℃";
59            }
60            tag += "</td>";
61        }
62        else{
63            tag += "<td class='center'>-</td>";
64        }
65 
66        tag += "</tr>";
67    }
68    tag += "</table>";
69    // 日付を整形
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>";
76    // 天気概況
77    tag += "<p class='description'>" + data.description.text + "</p>";
78 
79    result.innerHTML = tag;
80}
81 
82window.onload = function(){
83    result = document.getElementById("result");
84}

ライブドアお天気APIサービスのJSONデータ注意点

ライブドアお天気APIサービスのJSONデータの注意点として、時間帯によっては、最高気温や最低気温がなかったり、明後日の天気データが提供されていなかったりすることがあります。

わたしは今日、明日、明後日の最高気温と最低気温が必ずJSONデータとして返される情報として考えていましたが、違っていました。時間帯によって最高気温や最低気温がない場合があります。
やっかいなことにnullが返されてしまうので対策が必要でした。

今回は、

if(max != null){ // データが存在しているときの処理 }

などとしてチェックしています。

どうやら明日の天気データに関しては、常に最高気温最低気温が存在しているようです。

ライブドアお天気サービスWeb仕様に関しては以下を参考にしてください。
http://weather.livedoor.com/weather_hacks/webservice

コメント

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