定時飛行場実況気象通報式(METAR)とは
空港の気象状況について、航空機の離着陸のため自動で行った観測の成果(航空気象観測機器で観測された成果)を自動で通報している電文である。
空港の気象状況を取得するため、AVWX REST APIを用いて、METARを取得した。
プログラム
与論空港(RORY)の例
他の空港の場合はURLの最後を書き換えること
get_metar.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
与論空港(RORY)のMETARデータを取得するプログラム
"""
import json
import sys
from datetime import datetime
def get_cloud_type_japanese(cloud_type):
"""雲の種類を日本語に変換"""
cloud_types = {
'FEW': '少量 (1-2/8)',
'SCT': '散在 (3-4/8)',
'BKN': '曇り (5-7/8)',
'OVC': '曇天 (8/8)',
'CLR': '快晴',
'SKC': '快晴',
'VV': '垂直視程'
}
return cloud_types.get(cloud_type, cloud_type)
def format_datetime(dt_string):
"""日時を日本語形式にフォーマット"""
try:
dt = datetime.fromisoformat(dt_string.replace('Z', '+00:00'))
return dt.strftime('%Y年%m月%d日 %H:%M:%S UTC')
except:
return dt_string
def get_metar_data():
"""METARデータを取得 (requests が無ければ urllib 利用)"""
url_base = "https://avwx.rest/api/metar/RORY"
params = {
'options': '',
'airport': 'true',
'reporting': 'true',
'format': 'json'
}
headers = {
'Authorization': 'Token [your token]'
}
try:
r = requests.get(url_base, params=params, headers=headers, timeout=10)
r.raise_for_status()
return r.json()
except Exception as e:
print(f"APIリクエストエラー(requests): {e}")
sys.exit(1)
def display_metar_info(metar_data):
"""METAR情報を表示"""
print("=== 与論空港(RORY)METAR情報 ===")
print(f"生METAR: {metar_data.get('raw', 'N/A')}")
print(f"空港名: {metar_data.get('station', 'N/A')}")
# 観測時刻
time_info = metar_data.get('time', {})
if time_info.get('dt'):
print(f"観測時刻: {format_datetime(time_info['dt'])}")
# 風向・風速
wind_info = metar_data.get('wind')
if wind_info:
wind_dir = wind_info.get('direction', {}).get('value', 'N/A')
wind_speed = wind_info.get('speed', {}).get('value', 'N/A')
wind_unit = wind_info.get('speed', {}).get('unit', '')
print(f"風向: {wind_dir}度")
print(f"風速: {wind_speed} {wind_unit}")
# 突風
wind_gust = metar_data.get('wind_gust')
if wind_gust:
gust_value = wind_gust.get('value', 'N/A')
gust_unit = wind_gust.get('unit', '')
print(f"突風: {gust_value} {gust_unit}")
# 視程
visibility = metar_data.get('visibility')
if visibility:
vis_value = visibility.get('value', 'N/A')
vis_unit = visibility.get('unit', '')
print(f"視程: {vis_value} {vis_unit}")
# 気温
temperature = metar_data.get('temperature')
if temperature:
temp_value = temperature.get('value', 'N/A')
print(f"気温: {temp_value}°C")
# 露点
dewpoint = metar_data.get('dewpoint')
if dewpoint:
dew_value = dewpoint.get('value', 'N/A')
print(f"露点: {dew_value}°C")
# 湿度
humidity = metar_data.get('relative_humidity')
if humidity is not None:
print(f"相対湿度: {humidity:.1%}")
# 気圧
altimeter = metar_data.get('altimeter')
if altimeter:
alt_value = altimeter.get('value', 'N/A')
alt_unit = altimeter.get('unit', '')
print(f"気圧: {alt_value} {alt_unit}")
# 雲量情報
clouds = metar_data.get('clouds', [])
print("雲量:")
if not clouds:
print(" 快晴 (雲なし)")
else:
for i, cloud in enumerate(clouds, 1):
cloud_type = cloud.get('type', 'N/A')
altitude = cloud.get('altitude', 'N/A')
repr_str = cloud.get('repr', 'N/A')
type_jp = get_cloud_type_japanese(cloud_type)
print(f" 層{i}: {type_jp} - 高度 {altitude}00ft ({repr_str})")
# フライトルール
flight_rules = metar_data.get('flight_rules')
if flight_rules:
rules_jp = {
'VFR': '有視界飛行方式',
'MVFR': '制限有視界飛行方式',
'IFR': '計器飛行方式',
'LIFR': '低計器飛行方式'
}.get(flight_rules, flight_rules)
print(f"フライトルール: {rules_jp} ({flight_rules})")
def main():
"""メイン関数"""
try:
print("与論空港のMETARデータを取得中...")
metar_data = get_metar_data()
display_metar_info(metar_data)
print("\n=== 完全なJSONデータ ===")
print(json.dumps(metar_data, indent=2, ensure_ascii=False))
except KeyboardInterrupt:
print("\n処理が中断されました。")
sys.exit(1)
except Exception as e:
print(f"予期しないエラーが発生しました: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
レスポンス
与論空港の例
response.json
{
"altimeter": {
"repr": "Q1014",
"spoken": "one zero one four",
"value": 1014
},
"clouds": [
{
"altitude": 90,
"modifier": null,
"repr": "FEW090",
"type": "FEW"
},
{
"altitude": 130,
"modifier": null,
"repr": "SCT130",
"type": "SCT"
},
{
"altitude": 150,
"modifier": null,
"repr": "BKN150",
"type": "BKN"
}
],
"density_altitude": 1601,
"dewpoint": {
"repr": "25",
"spoken": "two five",
"value": 25
},
"flight_rules": "VFR",
"meta": {
"cache-timestamp": "2025-08-18T06:47:01.843000Z",
"stations_updated": "2024-12-02",
"timestamp": "2025-08-18T06:47:12.669593Z"
},
"other": [
"TCU"
],
"pressure_altitude": 29,
"raw": "RORY 180600Z AUTO 14007KT 9999 FEW090 SCT130 BKN150 //////TCU 28/25 Q1014",
"relative_humidity": 0.8377219417290783,
"remarks": "",
"remarks_info": null,
"runway_visibility": [],
"sanitized": "RORY 180600Z 14007KT 9999 FEW090 SCT130 BKN150 TCU 28/25 Q1014",
"station": "RORY",
"temperature": {
"repr": "28",
"spoken": "two eight",
"value": 28
},
"time": {
"dt": "2025-08-18T06:00:00Z",
"repr": "180600Z"
},
"units": {
"accumulation": "in",
"altimeter": "hPa",
"altitude": "ft",
"temperature": "C",
"visibility": "m",
"wind_speed": "kt"
},
"visibility": {
"repr": "9999",
"spoken": "nine nine nine nine",
"value": 9999
},
"wind_direction": {
"repr": "140",
"spoken": "one four zero",
"value": 140
},
"wind_gust": null,
"wind_speed": {
"repr": "07",
"spoken": "seven",
"value": 7
},
"wind_variable_direction": [],
"wx_codes": []
}
参考文献