1. NASA API 简介与准备工作
NASA作为全球顶尖的航天机构,向公众开放了大量宝贵的数据资源。这些数据涵盖了从地球观测到深空探测的各个领域,包括卫星图像、天文观测、气候数据等。通过API接口,开发者可以便捷地获取这些数据用于科研、教育或个人项目。
提示:NASA API是完全免费的,但需要注册获取API Key,每日调用次数限制为1000次。
1.1 注册NASA开发者账号
首先访问NASA开放数据门户,点击"Sign Up"按钮填写简单的注册表单。只需要提供姓名和邮箱地址,系统会立即生成一个专属的API Key。这个Key看起来像这样:DEMO_KEY(这是公开的演示Key,但建议使用自己注册的专属Key)。
1.2 了解API文档结构
NASA提供了多个数据接口,主要分为以下几类:
- 天文图片API(APOD)
- 地球观测数据(EONET)
- 火星探测器数据
- 小行星近地数据
- 卫星轨道数据
每个接口都有独立的文档说明,包含请求URL、参数和返回数据格式。建议先浏览官方文档了解各接口功能。
1.3 Python环境准备
确保你的Python环境已安装最新版本的requests库:
bash复制pip install requests pandas matplotlib
这三个库将分别用于:
requests:发送HTTP请求获取API数据pandas:处理和分析返回的JSON数据matplotlib:可视化展示数据
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础API调用:获取每日天文图片
2.1 APOD接口详解
天文图片每日一图(Astronomy Picture of the Day,APOD)是NASA最受欢迎的API之一。它每天更新一张天文相关的高清图片,并附带详细说明。
基础请求URL:
code复制https://api.nasa.gov/planetary/apod
可选参数:
date:指定日期(格式YYYY-MM-DD)hd:是否获取高清版本(True/False)count:获取多张图片(整数)thumbs:当媒体是视频时返回缩略图
2.2 Python实现代码
python复制import requests
import matplotlib.pyplot as plt
from PIL import Image
from io import BytesIO
def get_apod(api_key, date=None):
params = {'api_key': api_key}
if date:
params['date'] = date
response = requests.get('https://api.nasa.gov/planetary/apod', params=params)
data = response.json()
if 'url' in data:
image_url = data['url']
image_response = requests.get(image_url)
img = Image.open(BytesIO(image_response.content))
plt.figure(figsize=(10, 8))
plt.imshow(img)
plt.axis('off')
plt.title(data['title'])
plt.show()
print(f"日期: {data['date']}")
print(f"标题: {data['title']}")
print(f"说明: {data['explanation']}")
else:
print("今天的内容是视频:", data['url'])
# 使用示例
api_key = "你的API_KEY" # 替换为你的实际Key
get_apod(api_key, date="2023-07-20")
2.3 处理常见错误
当调用API时可能会遇到以下错误:
400 Bad Request:参数格式错误403 Forbidden:API Key无效或超过调用限制404 Not Found:请求的资源不存在
建议添加错误处理逻辑:
python复制try:
response = requests.get(url, params=params, timeout=10)
response.raise_for_status() # 检查HTTP错误
data = response.json()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return None
3. 进阶应用:处理地球观测数据
3.1 EONET接口介绍
地球观测事件API(Earth Observatory Natural Event Tracker,EONET)提供了全球正在发生的自然事件数据,如野火、风暴、火山喷发等。
基础端点:
code复制https://eonet.gsfc.nasa.gov/api/v3/events
3.2 数据获取与处理
python复制import pandas as pd
def get_eonet_events():
url = "https://eonet.gsfc.nasa.gov/api/v3/events"
response = requests.get(url)
data = response.json()
events = []
for event in data['events']:
events.append({
'id': event['id'],
'title': event['title'],
'category': event['categories'][0]['title'],
'date': event['geometry'][0]['date'],
'coordinates': f"{event['geometry'][0]['coordinates'][1]}, {event['geometry'][0]['coordinates'][0]}"
})
df = pd.DataFrame(events)
return df
# 使用示例
events_df = get_eonet_events()
print(events_df.head())
3.3 数据可视化
将获取的事件数据在地图上标记:
python复制import folium
def plot_events_on_map(df):
world_map = folium.Map(location=[20, 0], zoom_start=2)
for _, row in df.iterrows():
lat, lon = map(float, row['coordinates'].split(','))
folium.Marker(
location=[lat, lon],
popup=f"{row['title']} ({row['category']})",
icon=folium.Icon(color='red')
).add_to(world_map)
return world_map
# 使用示例
map_obj = plot_events_on_map(events_df)
map_obj.save('eonet_events.html')
4. 火星天气数据获取与分析
4.1 Mars Weather API
NASA的InSight火星探测器提供了火星表面的气象数据,包括温度、风速和气压等。
API端点:
code复制https://api.nasa.gov/insight_weather/
4.2 数据解析代码
python复制def get_mars_weather(api_key):
params = {
'api_key': api_key,
'feedtype': 'json',
'ver': '1.0'
}
response = requests.get('https://api.nasa.gov/insight_weather/', params=params)
data = response.json()
weather_data = []
for sol in data['sol_keys']:
sol_data = data[sol]
weather_data.append({
'火星日': sol,
'季节': sol_data['Season'],
'平均温度(°C)': sol_data['AT']['av'],
'最高温度': sol_data['AT']['mx'],
'最低温度': sol_data['AT']['mn'],
'气压(Pa)': sol_data['PRE']['av'],
'风速(m/s)': sol_data['HWS']['av'] if 'HWS' in sol_data else None
})
return pd.DataFrame(weather_data)
# 使用示例
mars_weather = get_mars_weather(api_key)
print(mars_weather)
4.3 数据可视化分析
python复制import seaborn as sns
def plot_mars_weather(df):
plt.figure(figsize=(12, 6))
plt.subplot(2, 2, 1)
sns.lineplot(data=df, x='火星日', y='平均温度(°C)')
plt.title('火星平均温度变化')
plt.subplot(2, 2, 2)
sns.lineplot(data=df, x='火星日', y='气压(Pa)')
plt.title('火星气压变化')
plt.subplot(2, 2, 3)
sns.barplot(data=df, x='季节', y='平均温度(°C)')
plt.title('季节温度对比')
plt.tight_layout()
plt.show()
# 使用示例
plot_mars_weather(mars_weather)
5. 性能优化与最佳实践
5.1 缓存API响应
为了避免重复请求相同数据,可以使用缓存机制:
python复制from datetime import datetime, timedelta
import os
import json
CACHE_DIR = 'nasa_cache'
os.makedirs(CACHE_DIR, exist_ok=True)
def cached_request(url, params, expire_hours=24):
cache_key = f"{url}?{'&'.join(f'{k}={v}' for k,v in params.items())}"
cache_file = os.path.join(CACHE_DIR, f"{hash(cache_key)}.json")
# 检查缓存是否存在且未过期
if os.path.exists(cache_file):
file_time = datetime.fromtimestamp(os.path.getmtime(cache_file))
if datetime.now() - file_time < timedelta(hours=expire_hours):
with open(cache_file, 'r') as f:
return json.load(f)
# 发送新请求并缓存结果
response = requests.get(url, params=params)
data = response.json()
with open(cache_file, 'w') as f:
json.dump(data, f)
return data
5.2 异步请求处理
当需要获取大量数据时,使用异步请求可以提高效率:
python复制import aiohttp
import asyncio
async def fetch_async(url, params, session):
async with session.get(url, params=params) as response:
return await response.json()
async def get_multiple_apods(dates, api_key):
async with aiohttp.ClientSession() as session:
tasks = []
for date in dates:
params = {'api_key': api_key, 'date': date}
task = fetch_async('https://api.nasa.gov/planetary/apod', params, session)
tasks.append(task)
return await asyncio.gather(*tasks)
# 使用示例
dates = ['2023-07-01', '2023-07-02', '2023-07-03']
results = asyncio.run(get_multiple_apods(dates, api_key))
5.3 错误处理与重试机制
实现一个健壮的重试机制:
python复制from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def robust_api_request(url, params):
response = requests.get(url, params=params, timeout=15)
response.raise_for_status()
return response.json()
6. 项目扩展思路
6.1 构建NASA数据仪表盘
使用Dash或Streamlit创建一个交互式仪表盘:
python复制import streamlit as st
def nasa_dashboard():
st.title('NASA数据仪表盘')
tab1, tab2, tab3 = st.tabs(["APOD", "EONET", "火星天气"])
with tab1:
date = st.date_input("选择日期")
if st.button('获取APOD'):
apod_data = get_apod(api_key, str(date))
# 显示结果...
with tab2:
if st.button('获取最新自然事件'):
eonet_data = get_eonet_events()
st.map(eonet_data) # 需要预处理坐标数据
with tab3:
if st.button('获取火星天气'):
mars_data = get_mars_weather(api_key)
st.line_chart(mars_data.set_index('火星日')['平均温度(°C)'])
# 运行: streamlit run your_script.py
6.2 数据持久化存储
将API数据保存到数据库供长期分析:
python复制import sqlite3
def init_db():
conn = sqlite3.connect('nasa_data.db')
c = conn.cursor()
# 创建APOD表
c.execute('''CREATE TABLE IF NOT EXISTS apod
(date TEXT PRIMARY KEY, title TEXT, explanation TEXT, url TEXT, media_type TEXT)''')
# 创建EONET表
c.execute('''CREATE TABLE IF NOT EXISTS eonet
(id TEXT PRIMARY KEY, title TEXT, category TEXT, date TEXT, lat REAL, lon REAL)''')
conn.commit()
conn.close()
def save_apod_to_db(data):
conn = sqlite3.connect('nasa_data.db')
c = conn.cursor()
c.execute('''INSERT OR REPLACE INTO apod VALUES (?,?,?,?,?)''',
(data['date'], data['title'], data['explanation'], data['url'], data.get('media_type','image')))
conn.commit()
conn.close()
6.3 自动化数据管道
使用Apache Airflow或Prefect构建自动化数据管道:
python复制from prefect import flow, task
from datetime import datetime, timedelta
@task
def fetch_daily_apod(api_key):
# 获取并存储当天的APOD
pass
@task
def fetch_eonet_events():
# 获取最新自然事件
pass
@flow(name="NASA数据管道")
def nasa_data_pipeline(api_key):
fetch_daily_apod(api_key)
fetch_eonet_events()
# 设置每天自动运行
if __name__ == "__main__":
nasa_data_pipeline.serve(name="daily-nasa-pipeline",
schedule=IntervalSchedule(interval=timedelta(days=1)))
