Spaces:
Sleeping
Sleeping
File size: 5,751 Bytes
f4202e1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
import requests
import gradio as gr
from datetime import datetime, timedelta
# USGS API 的基礎 URL
USGS_API_BASE_URL = "https://earthquake.usgs.gov/fdsnws/event/1/query"
def format_earthquake_info_markdown(data):
"""
將從 API 獲取的地震資料格式化為 Markdown 字串。
"""
if not data or 'features' not in data or not data['features']:
return "在指定的條件下,找不到任何地震資料。"
count = data['metadata']['count']
title = data['metadata']['title']
# 建立 Markdown 表格的標頭
md_output = f"## {title}\n\n"
md_output += f"**查詢成功,共找到 {count} 筆地震資料。**\n\n"
md_output += "| 時間 (UTC) | 地點 | 芮氏規模 | 深度 (公里) | 經緯度 |\n"
md_output += "|---|---|---|---|---|\n"
# 填入每一筆地震資料
for feature in data['features']:
properties = feature['properties']
geometry = feature['geometry']
event_time_utc = datetime.fromtimestamp(properties['time'] / 1000)
time_str = event_time_utc.strftime('%Y-%m-%d %H:%M:%S')
magnitude = properties['mag']
place = properties['place'].replace('|', '\|') # 避免 Markdown 表格語法衝突
longitude, latitude, depth = geometry['coordinates']
md_output += f"| {time_str} | {place} | {magnitude:.2f} | {depth:.2f} | ({latitude:.4f}, {longitude:.4f}) |\n"
return md_output
def query_earthquakes(
starttime_str: str,
endtime_str: str,
min_magnitude: float,
use_geo: bool,
min_lat: float, max_lat: float,
min_lon: float, max_lon: float
):
"""
接收來自 Gradio UI 的輸入,查詢並回傳格式化的地震資料。
"""
params = {
"format": "geojson",
"starttime": starttime_str,
"endtime": endtime_str,
"minmagnitude": min_magnitude,
"limit": 500, # 限制回傳數量,避免 UI 過於壅塞
"orderby": "time"
}
# 如果使用者勾選了 "指定地理範圍"
if use_geo:
# 簡單的驗證
if not all([min_lat, max_lat, min_lon, max_lon]):
return "錯誤:若要指定地理範圍,則經緯度四個欄位皆須填寫。"
if min_lat >= max_lat or min_lon >= max_lon:
return "錯誤:最小經緯度必須小於最大經緯度。"
params.update({
"minlatitude": min_lat,
"maxlatitude": max_lat,
"minlongitude": min_lon,
"maxlongitude": max_lon
})
try:
response = requests.get(USGS_API_BASE_URL, params=params, timeout=20)
response.raise_for_status()
data = response.json()
return format_earthquake_info_markdown(data)
except requests.exceptions.RequestException as e:
return f"錯誤:網路請求失敗: {e}"
except Exception as e:
return f"發生未知錯誤: {e}"
# --- Gradio 介面設計 ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🌎 USGS 地震資料查詢工具")
gr.Markdown("透過此工具,您可以查詢美國地質調查局 (USGS) 的全球地震紀錄。")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 1. 設定查詢條件")
# 預設查詢時間為過去 7 天
today = datetime.now()
seven_days_ago = today - timedelta(days=7)
starttime_input = gr.Textbox(label="查詢開始日期", value=seven_days_ago.strftime('%Y-%m-%d'))
endtime_input = gr.Textbox(label="查詢結束日期", value=today.strftime('%Y-%m-%d'))
magnitude_slider = gr.Slider(
minimum=0, maximum=10, step=0.1,
label="最小芮氏規模",
value=4.5
)
gr.Markdown("### 2. (可選) 指定地理範圍")
use_geo_checkbox = gr.Checkbox(label="啟用地理範圍篩選", value=False)
with gr.Row():
min_lat_input = gr.Number(label="最小緯度 (南)", value=21.5)
max_lat_input = gr.Number(label="最大緯度 (北)", value=25.5)
with gr.Row():
min_lon_input = gr.Number(label="最小經度 (西)", value=120.0)
max_lon_input = gr.Number(label="最大經度 (東)", value=122.5)
submit_btn = gr.Button("開始查詢", variant="primary")
with gr.Column(scale=3):
gr.Markdown("### 查詢結果")
output_markdown = gr.Markdown("點擊「開始查詢」後,結果將會顯示於此。")
# 綁定按鈕點擊事件
submit_btn.click(
fn=query_earthquakes,
inputs=[
starttime_input,
endtime_input,
magnitude_slider,
use_geo_checkbox,
min_lat_input, max_lat_input,
min_lon_input, max_lon_input
],
outputs=output_markdown
)
gr.Examples(
examples=[
[seven_days_ago.strftime('%Y-%m-%d'), today.strftime('%Y-%m-%d'), 6.0, False, 0, 0, 0, 0],
["2024-04-02", "2024-04-04", 5.5, True, 23.0, 25.0, 121.0, 122.5],
["2024-01-01", "2024-01-02", 7.0, True, 35.0, 38.0, 136.0, 140.0],
],
inputs=[
starttime_input,
endtime_input,
magnitude_slider,
use_geo_checkbox,
min_lat_input, max_lat_input,
min_lon_input, max_lon_input
],
outputs=output_markdown,
fn=query_earthquakes,
cache_examples=True # 讓範例結果快取,加速載入
)
if __name__ == "__main__":
demo.launch()
|