小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


PHPとJavaScriptで地震感知情報取得APIから地震情報を取得する

はじめに

関東東北震災以降、東北地方や茨城県などで強い余震が続いています。離れて暮らしていても、やっぱり怖いものです。緊急地震速報を見逃すまいと、NHKばかり見ている今日この頃です。というわけで、このエントリでは、PHPとJavaScriptを使って、EPSP(partA) 地震感知情報APIから地震の震源地やマグニチュードなどの情報を取得してみたいと思います。

これは、地震感知情報APIを用いた地震感知情報データの取得方法及び解析方法についてを提供するものです。
EPSP(partA) 地震感知情報APIにおける開発者向け情報 はてなブックマーク - EPSP(partA) 地震感知情報APIにおける開発者向け情報

地震感知情報APIの呼び出し

地震感知情報APIの呼び出しは、PHPで行います。JavaScriptからPHPを非同期で呼び出し、そこから地震感知情報APIにアクセスしています。関東東北震災以降、地震感知情報APIに大量のアクセスが来ているそうで、APIになるべく負荷をかけないようにするため、APC(Alternative PHP Cache)でキャッシュする処理が入っています。

APIによるデータ転送が、 p2pquake.ddo.jp 上り回線の90% を占める状態となり、地震情報以外の提供を中止させていただきました。
転送量軽減のため、従来通りの提供体制に復帰するために、キャッシュ(15秒〜1分程度で構いません)を取るなどの対応をお願いします。お手数をおかけします。
P2P地震情報 開発ログ: "地震感知情報API"をご利用のサービス提供者さまへお願い はてなブックマーク - P2P地震情報 開発ログ:

サーバサイド(PHP)

サーバサイドのPHPはこんな感じです。キャッシュヒットしない場合は、file_get_contentsでAPIを呼び出しにいきます。

<?PHP

date_default_timezone_set('Asia/Tokyo');

getEI();
function getEI() {
  header("Content-Type: text/html; charset=shift_JIS");
  $url = "http://p2pquake.ddo.jp/p2pquake/api_userquake.pl?";
  $url = $url . "date=" . date("m/d");
  try {
    // キャッシュから取り出し
    $html = apc_fetch($url);
    // キャッシュヒットしなかったら、file_get_contentsで取りに行く
    if ($html === false) {
      $html = file_get_contents($url, false, NULL);
      if($html != FALSE) {
        // 60秒間キャッシュする
        apc_store($url, $html, 60);
        echo $html;
      }
      else {
        echo "地震感知情報APIへの接続に失敗しました。(1)<br>";
      }
    }
    else {
    	// キャッシュヒットした場合
      echo $html;
    }
  } catch (Exception $e) {
    echo "地震感知情報APIへの接続に失敗しました。(2)<br>";
    echo $e->getMessage(); 
  }
  return true;
}
?>
クライアントサイド(JavaScript)

クライアントサイドでは、APIから返ってきたテキストデータを解析して、テーブルとして表示してやります。

function getEI() {
  var xmlHttp = new XMLHttpRequest();
  xmlHttp.onreadystatechange = function() {
    if (xmlHttp.readyState == 4) {
      if (xmlHttp.status == 200) {
        // ロード完了したときの処理
        
        // ローディングインジケータを非表示
        document.getElementById("loadingImg").style.display = "none";
        // データの解析
        var record = xmlHttp.responseText.split("\n");
        for(var i=0, len=record.length; i<len; i++) {
          var arrCommaSep = record[i].split(",");
          // 地震情報データ(QUA)の場合だけ処理する
          if (arrCommaSep[1] === "QUA") {
            var arrTmp = arrCommaSep[2].split("/");
            var tr = document.createElement("tr");
            for(var j=0, len2=arrTmp.length; j<len2; j++) {
              var td = document.createElement("td");
              // 津波の有無
              if (j === 2) {
                td.innerHTML = getTsunami(arrTmp[j]);
              }
              // 地震情報種類
              else if(j === 3) {
                td.innerHTML = getEIClass(arrTmp[j]);
              }
              // 震度訂正
              else if(j === 7) {
                td.innerHTML = IntensityCorrection(arrTmp[j]);
              }
              else {
                td.innerHTML = arrTmp[j];
              }
              tr.appendChild(td);
            }
            document.getElementById("tbl").appendChild(tr);
          }
        }
      }
      else {
        // 通信失敗
        document.getElementById("loadingImg").style.display = "none";
        alert("通信中にエラー発生::" + xmlHttp.status);
      }
    }
    else {
      // ロード中
      document.getElementById("loadingImg").style.display = "inline";
    }
  }
  var url = "./getEI.php" 
  xmlHttp.open("GET", url, true); 
  xmlHttp.send(null);
}

// 津波の有無
function getTsunami(n) {
  switch(parseInt(n)) {
    case 0:
      return "なし";
      break;
  case 1:
      return "あり";
      break;
  case 2:
      return "調査中";
      break;
  case 3:
      return "不明";
      break;
  }
}

// 地震情報種類
function getEIClass(n) {
  switch(parseInt(n)) {
  case 1:
      return "震度速報";
      break;
  case 2:
      return "震源情報";
      break;
  case 3:
      return "震源・震度情報";
      break;
  case 4:
      return "震源・詳細震度情報";
      break;
  case 5:
      return "遠地地震情報";
      break;
  }
}

// 震度訂正
function IntensityCorrection(n) {
  switch(parseInt(n)) {
  case 0:
      return "いいえ";
      break;
  case 1:
      return "はい";
      break;
  }
}
デモアプリ

「地震情報をロードする」ボタンを押すと、地震感知情報APIから今日の地震情報を取得し、一覧表として表示します。Google Mapとの連携やソート機能などが実装できると良い感じになるかも。