PHPで全国の災害警戒情報を表示する

(1/1)
PHPを使って気象庁防災情報XMLから、全国の記録的短時間大雨情報、土砂災害警戒情報を取得し、一覧表示するプログラムを作る。

サンプル・プログラムの実行例

PHPで全国の災害警戒情報を表示する

目次

サンプル・プログラム

圧縮ファイルの内容
jmaDisasterWarning.phpサンプル・プログラム本体。
pahooCache.phpキャッシュ処理に関わるクラス pahooCache。
キャッシュ処理に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
jmaDisasterWarning.php 更新履歴
バージョン 更新日 内容
1.0.0 2025/08/11 初版
pahooCache.php 更新履歴
バージョン 更新日 内容
1.1.3 2025/08/10 var→public
1.1.2 2023/07/22 bug-fix
1.1.1 2023/02/11 コメント追記
1.1 2021/04/08 simplexml_load()メソッド追加
1.0 2021/04/02 初版
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加
1.7.0 2024/10/09 validURL() validEmail() 追加
1.6.0 2024/10/07 isButton() buttonタグに対応

気象庁防災情報XMLフォーマット

気象庁防災情報XMLフォーマットは、気象や地震、火山に関する情報を随時流している。
まず、下表の6つの Atomフィードにアクセスし、必要なXML情報のURLを求める。
フィードの構造(xml) feed title タイトル subtitle サブタイトル updated 配信日時 id ID rights 著作権表記 entry title XML情報タイトル(1) id XML情報のURL(1) updated 更新日時(1) author name 作者(1) content 内容説明(1) entry title XML情報タイトル(2) id XML情報のURL(2) updated 更新日時(2) author name 作者(2) content 内容説明(2)
XML情報のURLの命名規則は以下の通り。
https://www.data.jma.go.jp/developer/xml/data/yyyymmddhhmmss_番号_電文コード_連番.xml
長期フィードの随時の中にある電文コード VPOA50 に記録的短時間大雨情報に関する情報が、同じく電文コード VXWW50 に土砂災害警戒情報に関する情報が入っている。

準備:PHP の https対応

クラウド連携や相手先サイトのデータを読み込むのに https通信を使うため、PHPに OpenSSLモジュールが組み込まれている必要がある。関数  phpinfo  を使って、下図のように表示されればOKだ。
OpenSSL - PHP
そうでない場合は、次の手順に従ってOpenSSLを有効化し、PHPを再起動させる必要がある。

Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dll
Linuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順

これで準備は完了だ。

準備:pahooCache クラス

pahooCache.php

  13: class pahooCache {
  14:     const LIFE_CACHE = (2 * 60);        // キャッシュ保持時間(デフォルト;分)
  15:     const DEF_DIRCACHE = './pcache/';   // キャッシュ・ディレクトリ(デフォルト)
  16: 
  17:     public $lifeCache;      // キャッシュ保持時間(分)(0:キャッシュしない)
  18:     public $dirCache;       // キャッシュ用ディレクトリ
  19:     public $error;          // エラーフラグ
  20:     public $errmsg;         // エラーメッセージ
  21:     public $debug;          // デバッグ用ファイル名
  22: 
  23: /**
  24:  * コンストラクタ
  25:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-72-01.shtm
  26:  * @param   int    $life キャッシュ保持時間(分)(省略可能)
  27:  * @param   string $dir キャッシュ・ディレクトリ(省略可能)
  28:  * @return  なし
  29: */
  30: function __construct($life=self::LIFE_CACHE, $dir=self::DEF_DIRCACHE) {
  31:     if ($life < 0) {
  32:         $life = 0;
  33:     }
  34:     if (preg_match('/\/$/ui', $dir) == 0) {
  35:         $dir = $dir . '/';
  36:     }
  37:     $this->error      = FALSE;
  38:     $this->errmsg     = '';
  39:     $this->debug      = '';
  40:     $this->lifeCache = $life;
  41:     $this->dirCache  = $dir;
  42: 
  43:     // PHP5以上であることを調べる.
  44:     if (! $this->isphp5over()) {
  45:         $this->error   = TRUE;
  46:         $this->errmsg  = '動作にはPHP5以上が必要です';
  47:         return;
  48:     }
  49: 
  50:     // キャッシュ・ディレクトリが無ければ作成する.
  51:     if (! is_dir($this->dirCache)) {
  52:         $res = mkdir($this->dirCache, 0744);
  53:         if ($res == FALSE) {
  54:             $this->error   = TRUE;
  55:             $this->errmsg  = 'キャッシュ・ディレクトリ "' . $this->$dirCache . '" の作成に失敗しました';
  56:             return;
  57:         }
  58:     }
  59: }

クラウド連携や相手先サイトの公開データを利用する際、こちらのアプリを起動する都度、APIを呼び出したりデータをダウンロードするのでは、相手サーバに負荷をかけてしまう。
そこで、頻繁に変更がないデータについては、一度取り込んだら、こちら側のサーバのローカルストレージにキャッシュしておく仕組みを用意した。それが pahooCacheクラス である。同梱のクラス・ファイル "pahooCache.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooCacheクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

pahooCacheクラス の注意ポイントは、キャッシュ時間(単位:分)とキャッシュを保存するディレクトリをコンストラクタで指定している点だ。これらはプログラムによって変わるものである。インスタンス化するときの値は、pahooCacheクラス を利用するメイン・プログラムの方で解説する。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooGeoCode.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

準備:各種定数など

jmaDisasterWarning.php

  61: // 各種定数(START) ===========================================================
  62: 
  63: // 表示幅(単位:ピクセル)
  64: define('WIDTH',  800);
  65: 
  66: // Twitter(現・X)投稿ボタン  TRUE:有効,FALSE:無効【未実装】
  67: define('TWITTER', FALSE);
  68: 
  69: // Bluesky投稿ボタン  TRUE:有効,FALSE:無効【未実装】
  70: define('BLUESKY', FALSE);
  71: 
  72: // 画像化したいオブジェクト
  73: define('TARGET', 'target');
  74: 
  75: // キャッシュ保持時間(分) 0:キャッシュしない
  76: // 気象庁へのアクセス負荷軽減のため,適切な時間を設定してください.
  77: define('LIFE_CACHE_FEED',     5);       // 高頻度 - 随時フィードに対して
  78: define('LIFE_CACHE_DATA',   360);       // 個々の災害警戒情報に対して
  79: 
  80: // キャッシュ・ディレクトリ
  81: // 書き込み可能で,外部からアクセスされないディレクトリを指定してください.
  82: // 天気予報系のプログラムとは別のディレクトリを指定してください.
  83: define('DIR_CACHE_FEED',   './pcache1/');
  84: define('DIR_CACHE_DATA',   './pcache2/');
  85: 
  86: // これより古い情報は無視する(単位:時間)
  87: define('INTERVAL', 12);
  88: 
  89: // 気象庁防災情報XML:高頻度フィード - 随時【変更不可】
  90: define('FEED', 'https://www.data.jma.go.jp/developer/xml/feed/extra.xml');
  91: 
  92: // 各種定数(END) ============================================================

各種定数などの内容は、プログラムのコメントに記載した通りである。「変更不可」以外の定数は自由に変更できる。

jmaDisasterWarning.php

  54: // 電文コードと取得関数の対応表
  55: $FunctionList = array(
  56:     'VPOA50' => 'getVPOA50',        // 記録的短時間大雨情報
  57:     'VXWW50' => 'getVPWW50',        // 土砂災害警戒情報
  58: //  'VPWW53' => 'getVPWW53',        // 気象特別警報・警報・注意報【未実装】
  59: );

複数の XML情報から情報を集めて回るので、電文コードとそれに対応する取得関数の一覧を用意しておく。
この配列を変更することで、ここに掲載していない XML情報を取得することができる。

解説:気象庁防災情報XMLから災害警戒情報に関する情報URL群を取得

jmaDisasterWarning.php

 347: /**
 348:  * 気象庁防災情報XMLから災害警戒情報に関する情報URL群を取得
 349:  * @param   array  $items   情報URLとコードを格納する配列
 350:  * @param   string $errmsg  エラーメッセージを格納する
 351:  * @return  int 取得件数/FALSE:取得失敗
 352: */
 353: function jmaGetDisasterWarningURLs(&$items, &$errmsg) {
 354:     global $FunctionList;
 355: 
 356:     // エラーをリセットする
 357:     $errmsg = '';
 358: 
 359:     // インスタンス生成
 360:     $pcc = new pahooCache(LIFE_CACHE_FEED, DIR_CACHE_FEED);
 361: 
 362:     // 随時フィードの解析
 363:     $cnt = 0;
 364:     $xml = $pcc->simplexml_load(FEED);
 365:     // レスポンス・チェック
 366:     if ($pcc->iserror() || !isset($xml->entry)) {
 367:         $errmsg = '気象庁防災情報XMLにアクセスできません';
 368:         return FALSE;
 369:     }
 370:     foreach ($xml->entry as $node) {
 371:         // URLを取得
 372:         foreach ($FunctionList as $code=>$func) {
 373:             $reg = '/https?\:\/\/www\.data\.jma\.go\.jp\/developer\/xml\/data\/([0-9\_]+)' . $code . '\_[0-9]+\.xml/ui';
 374:             if (preg_match($reg, (string)$node->id, $arr> 0) {
 375:                 $items[$cnt]['code'] = $code;
 376:                 $items[$cnt]['url']  = $arr[0];
 377:                 $cnt++;
 378:             }
 379:         }
 380:     }
 381:     $pcc = NULL;
 382: 
 383:     // URLを日時の新しい順にソート
 384:     if (count($items> 0) {
 385:         usort($items, function($a, $b) {
 386:             return ($a['url'> $b['url']) ? -1 : +1;
 387:         });
 388:     }
 389: 
 390:     // インスタンス解放
 391:     $pcc = NULL;
 392: 
 393:     return $cnt;
 394: }

前述のフィードから、災害警戒情報に関する情報URLを取得するユーザー関数が jmaGetDisasterWarningURLs である。
指定した電文コードにマッチするURLを配列 $items に格納していき、最後に配列 $items を大きい順にソートすることで、日付の新しい順にソートしたことになる。

解説:記録的短時間大雨情報を取得

jmaDisasterWarning.php

 396: /**
 397:  * 記録的短時間大雨情報を取得(気象庁防災情報XMLから)
 398:  * @param   string $url    気象庁防災情報XMLのURL
 399:  * @param   array  $info   情報を格納する配列
 400:  * @param   string $errmsg エラーメッセージを格納する
 401:  * @return  bool TRUE:取得成功/FALSE:失敗
 402: */
 403: function getVPOA50($url, &$info, &$errmsg) {
 404:     // インスタンス生成
 405:     $pcc = new pahooCache(LIFE_CACHE_DATA, DIR_CACHE_DATA);
 406:     $xml = $pcc->simplexml_load($url);
 407: 
 408:     // 報告日時
 409:     if (isset($xml->Head->ReportDateTime)) {
 410:         $info['dt'] = (string)$xml->Head->ReportDateTime;
 411:     } else {
 412:         $errmsg = $url . ' の情報を取得できません';
 413:         return FALSE;
 414:     }
 415: 
 416:     // 情報タイトル
 417:     if (isset($xml->Head->Title)) {
 418:         $info['title'] = deleteSpaces((string)$xml->Head->Title);
 419:     } else {
 420:         $errmsg = $url . ' の情報を取得できません';
 421:         return FALSE;
 422:     }
 423: 
 424:     // 情報内容
 425:     if (isset($xml->Head->Headline->Text)) {
 426:         $info['description'] = replaceSpaces((string)$xml->Head->Headline->Text);
 427: ;
 428:     } else {
 429:         $errmsg = $url . ' の情報を取得できません';
 430:         return FALSE;
 431:     }
 432: 
 433:     // インスタンス解放
 434:     $pcc = NULL;
 435: 
 436:     return TRUE;
 437: }

電文コード VPOA50 に対応する記録的短時間大雨情報を取得するユーザー関数が getVPOA50 である。
報告日時、情報タイトル+情報内容を取得し、配列 $info に格納して返す。

解説:土砂災害警戒情報を取得

jmaDisasterWarning.php

 439: /**
 440:  * 土砂災害警戒情報(気象庁防災情報XMLから)
 441:  * @param   string $url    気象庁防災情報XMLのURL
 442:  * @param   array  $info   情報を格納する配列
 443:  * @param   string $errmsg エラーメッセージを格納する
 444:  * @return  bool TRUE:取得成功/FALSE:失敗
 445: */
 446: function getVPWW50($url, &$info, &$errmsg) {
 447:     // インスタンス生成
 448:     $pcc = new pahooCache(LIFE_CACHE_DATA, DIR_CACHE_DATA);
 449:     $xml = $pcc->simplexml_load($url);
 450: 
 451:     // 報告日時
 452:     if (isset($xml->Head->ReportDateTime)) {
 453:         $info['dt'] = (string)$xml->Head->ReportDateTime;
 454:     } else {
 455:         $errmsg = $url . ' の情報を取得できません';
 456:         return FALSE;
 457:     }
 458: 
 459:     // 情報タイトル
 460:     if (isset($xml->Head->Title)) {
 461:         $info['title'] = deleteSpaces((string)$xml->Head->Title);
 462:     } else {
 463:         $errmsg = $url . ' の情報を取得できません';
 464:         return FALSE;
 465:     }
 466: 
 467:     // 情報内容
 468:     if (isset($xml->Head->Headline->Text)) {
 469: //      $info['description'] = deleteSpaces((string)$xml->Head->Headline->Text);
 470:         $info['description'] = nl2br(trim((string)$xml->Head->Headline->Text));
 471:     } else {
 472:         $errmsg = $url . ' の情報を取得できません';
 473:         return FALSE;
 474:     }
 475: 
 476:     // インスタンス解放
 477:     $pcc = NULL;
 478: 
 479:     return TRUE;
 480: }

電文コード VPWW50 に対応する土砂災害警戒情報を取得するユーザー関数が getVPWW50 である。
報告日時、情報タイトル+情報内容を取得し、配列 $info に格納して返す。

参考サイト

(この項おわり)
header