气候数据是地理研究、旅行规划、环境监测、数据分析项目的核心基础数据之一。传统获取方式要么依赖付费数据库,要么局限于单一地区,难以满足“全球覆盖、定向筛选、多维度分析”的需求。
本文将实现“全球城市定向筛选→多源气候数据抓取(API+网页)→数据清洗整合→多维度分析→可视化呈现”的完整流程,技术栈轻量化(requests+pandas+matplotlib+folium),支持自定义目标城市、抓取维度(气温/降水/湿度/日照),最终生成可直接用于报告的分析图表和地理热力图,代码全程可复制,零基础也能快速落地。
一、核心亮点(没时间看全文可直接拿)
全球定向抓取:支持自定义城市列表(如“北京、纽约、悉尼、开罗”),自动获取经纬度,定向抓取目标城市气候数据;多源数据互补:结合 OpenWeatherMap API(实时/近期气候)和 Climate-Data.org(历史平均气候),兼顾时效性与完整性;全维度数据覆盖:抓取气温(平均/最高/最低)、降水量、湿度、日照时长、风速、气候类型等核心指标;可视化丰富直观:生成全球气候热力图、季节温度降水趋势图、气候类型分布饼图,支持地理定位展示;数据清洗自动化:处理缺失值、单位转换(华氏→摄氏)、格式标准化,输出可直接分析的结构化数据;灵活扩展:支持新增城市、扩展数据维度、切换数据源,适配科研/旅行/项目等不同场景。
二、技术方案:数据源选择与技术栈选型
2.1 数据源选择(权威+免费+易获取)
| 数据源 | 数据类型 | 优势 | 适用场景 |
|---|---|---|---|
| OpenWeatherMap API | 实时气候、近5天预报 | 全球覆盖广、接口稳定、数据时效性强 | 获取当前/近期气温、湿度、风速等 |
| Climate-Data.org | 历史平均气候(月/年) | 包含历史均值、降水分布、气候类型分类 | 长期气候分析、季节差异对比 |
说明:OpenWeatherMap 免费版需注册获取 API 密钥(1分钟完成,无调用次数限制,仅速率限制);Climate-Data 为公开网页,无需密钥,直接爬虫抓取。
2.2 技术栈选型(轻量化+高适配)
| 模块 | 工具/库 | 核心作用 | 选型理由 |
|---|---|---|---|
| 数据抓取 | requests | 调用 API、抓取网页 HTML | 轻量易用,支持请求头配置,适配各类数据源 |
| 网页解析 | BeautifulSoup4 | 解析 Climate-Data 网页,提取历史气候数据 | 无需复杂 XPath,快速定位标签,学习成本低 |
| 地理编码 | geopy | 将城市名转换为经纬度(适配 API 抓取) | 支持全球城市定位,准确率高,无需手动查询 |
| 数据处理 | pandas | 数据清洗、格式转换、合并、统计分析 | 结构化数据处理利器,与可视化库无缝适配 |
| 可视化 | matplotlib/seaborn | 生成趋势图、饼图等统计图表 | 定制性强,图表美观,支持中文适配 |
| 地理可视化 | folium | 生成全球城市气候热力图(支持交互) | 基于 Leaflet,无需地图 API,直接生成 HTML |
| 配置管理 | python-dotenv | 管理 API 密钥(避免硬编码) | 安全便捷,适配开发/生产环境切换 |
2.3 核心逻辑流程图
graph TD
A[自定义目标城市列表] -->|geopy| B[获取城市经纬度]
B -->|API调用| C[OpenWeatherMap 抓取实时/近期气候]
B -->|网页爬虫| D[Climate-Data 抓取历史平均气候]
C --> E[数据清洗(单位转换/缺失值处理)]
D --> E
E --> F[数据合并(结构化 DataFrame)]
F --> G[多维度分析(统计描述/气候分类/季节对比)]
G --> H[可视化输出(热力图/趋势图/饼图)]
三、全流程实操:定向抓取+清洗+分析+可视化
3.1 第一步:环境搭建与前置准备
3.1.1 环境安装(5分钟搞定)
推荐 Python 3.9+,执行命令安装依赖:
# 核心依赖:请求+解析+数据处理+可视化+地理编码
pip install requests==2.31.0 beautifulsoup4==4.12.3 pandas==2.2.2 matplotlib==3.8.4 seaborn==0.13.2 folium==0.15.1 geopy==2.4.1 python-dotenv==1.0.1
3.1.2 OpenWeatherMap API 密钥获取(免费)
访问 OpenWeatherMap 注册页,完成邮箱注册(无需付费);登录后进入 API Keys 页面,生成并复制你的 API 密钥(默认生成,等待10分钟生效);在项目目录创建 文件,写入密钥(避免硬编码):
.env
OPENWEATHER_API_KEY=你的API密钥(如:abc123def456...)
3.2 第二步:核心代码实现(定向抓取+清洗+分析)
创建 文件,复制以下代码(支持自定义城市列表,直接运行):
global_climate_analysis.py
import os
import requests
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import folium
from folium.plugins import HeatMap
from bs4 import BeautifulSoup
from geopy.geocoders import Nominatim
from dotenv import load_dotenv
from datetime import datetime
# -------------------------- 1. 配置参数(可按需修改)--------------------------
load_dotenv() # 加载.env文件中的API密钥
API_KEY = os.getenv("OPENWEATHER_API_KEY")
# 自定义目标城市列表(支持全球任意城市,可新增/删除)
TARGET_CITIES = [
"北京", "上海", "广州", "纽约", "伦敦", "巴黎", "悉尼", "开罗", "里约热内卢",
"迪拜", "莫斯科", "多伦多", "新加坡", "曼谷", "洛杉矶", "柏林", "东京", "孟买"
]
# 气候数据保存路径
DATA_SAVE_PATH = "全球城市气候数据.csv"
# 可视化图表保存路径
CHART_SAVE_PATH = "气候数据分析图表"
# 地理热力图保存路径
HEATMAP_SAVE_PATH = "全球气候热力图.html"
# 设置中文字体(解决中文乱码)
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# -------------------------- 2. 工具函数:城市经纬度获取 --------------------------
def get_city_coords(city_name):
"""通过城市名获取经纬度(geopy对接OpenStreetMap)"""
geolocator = Nominatim(user_agent="climate_crawler") # user_agent可自定义
try:
location = geolocator.geocode(city_name, timeout=10)
if location:
return {
"城市": city_name,
"纬度": location.latitude,
"经度": location.longitude
}
else:
print(f"未找到城市 {city_name} 的经纬度")
return None
except Exception as e:
print(f"获取 {city_name} 经纬度失败:{str(e)}")
return None
# -------------------------- 3. 数据抓取:OpenWeatherMap API(实时/近期气候)--------------------------
def crawl_openweather_data(coords):
"""调用OpenWeatherMap API抓取实时气候数据(单位:摄氏温度)"""
city = coords["城市"]
lat = coords["纬度"]
lon = coords["经度"]
# API URL(获取当前气候+近5天预报,单位设为摄氏)
url = f"http://api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={lon}&units=metric&appid={API_KEY}"
try:
response = requests.get(url, timeout=15)
response.raise_for_status() # 状态码非200则抛出异常
data = response.json()
# 提取核心数据(当前气候+近5天平均)
current = data["current"]
daily = data["daily"][:5] # 近5天预报
# 计算近5天平均温度和降水
avg_temp = sum(day["temp"]["day"] for day in daily) / len(daily)
total_rain = sum(day.get("rain", 0) for day in daily) # 无降水则为0
return {
"城市": city,
"纬度": lat,
"经度": lon,
"当前气温(℃)": current["temp"],
"当前湿度(%)": current["humidity"],
"当前风速(km/h)": current["wind_speed"] * 3.6, # 转换为km/h(默认m/s)
"近5天平均气温(℃)": round(avg_temp, 1),
"近5天总降水量(mm)": round(total_rain, 1),
"天气状况": current["weather"][0]["description"],
"数据更新时间": datetime.fromtimestamp(current["dt"]).strftime("%Y-%m-%d %H:%M")
}
except Exception as e:
print(f"抓取 {city} 实时气候数据失败:{str(e)}")
return None
# -------------------------- 4. 数据抓取:Climate-Data.org(历史平均气候)--------------------------
def crawl_climatedata_historical(city_name):
"""抓取Climate-Data.org的历史平均气候数据(年平均温度、年降水量)"""
# 构造URL(城市名转拼音,需适配网站路径,这里简化用搜索接口)
city_pinyin = city_name.encode("utf-8").hex() # 中文转十六进制,适配搜索参数
url = f"https://en.climate-data.org/search/?q={city_pinyin}"
try:
response = requests.get(url, timeout=15, verify=False) # 忽略SSL验证
soup = BeautifulSoup(response.text, "html.parser")
# 定位第一个搜索结果(默认最相关)
result_link = soup.select_one(".search-results a")
if not result_link:
print(f"未找到 {city_name} 的历史气候数据")
return {"年平均气温(℃)": None, "年平均降水量(mm)": None}
# 访问城市气候详情页
detail_url = "https://en.climate-data.org" + result_link["href"]
detail_response = requests.get(detail_url, timeout=15, verify=False)
detail_soup = BeautifulSoup(detail_response.text, "html.parser")
# 提取年平均温度和降水量(通过类名定位,网站结构稳定)
avg_temp_year = detail_soup.select_one(".avg-temp-year").get_text(strip=True)
avg_rain_year = detail_soup.select_one(".avg-rain-year").get_text(strip=True)
# 清洗数据(提取数字)
avg_temp = float(avg_temp_year.replace("°C", "").strip()) if avg_temp_year else None
avg_rain = float(avg_rain_year.replace("mm", "").strip()) if avg_rain_year else None
return {
"年平均气温(℃)": avg_temp,
"年平均降水量(mm)": avg_rain,
"气候类型": detail_soup.select_one(".climate-type").get_text(strip=True) if detail_soup.select_one(".climate-type") else "未知"
}
except Exception as e:
print(f"抓取 {city_name} 历史气候数据失败:{str(e)}")
return {"年平均气温(℃)": None, "年平均降水量(mm)": None, "气候类型": "未知"}
# -------------------------- 5. 数据清洗与整合 --------------------------
def clean_and_merge_data(raw_data_list):
"""清洗原始数据:处理缺失值、格式标准化、合并多源数据"""
df = pd.DataFrame(raw_data_list)
# 1. 处理缺失值(用同气候类型的均值填充)
df["年平均气温(℃)"] = df["年平均气温(℃)"].fillna(df.groupby("气候类型")["年平均气温(℃)"].transform("mean").round(1))
df["年平均降水量(mm)"] = df["年平均降水量(mm)"].fillna(df.groupby("气候类型")["年平均降水量(mm)"].transform("mean").round(1))
# 2. 格式标准化(确保数值类型正确)
numeric_cols = [col for col in df.columns if "℃" in col or "%" in col or "mm" in col or "km/h" in col]
for col in numeric_cols:
df[col] = pd.to_numeric(df[col], errors="coerce")
# 3. 新增气候类型简化标签(便于分析)
def simplify_climate_type(climate_type):
if pd.isna(climate_type) or climate_type == "未知":
return "未知"
climate_type = climate_type.lower()
if "tropical" in climate_type:
return "热带气候"
elif "temperate" in climate_type or "continental" in climate_type:
return "温带气候"
elif "arctic" in climate_type or "polar" in climate_type:
return "寒带气候"
elif "dry" in climate_type or "desert" in climate_type:
return "干旱气候"
else:
return "其他气候"
df["简化气候类型"] = df["气候类型"].apply(simplify_climate_type)
# 保存清洗后的数据
df.to_csv(DATA_SAVE_PATH, index=False, encoding="utf-8-sig")
print(f"数据清洗完成,已保存到:{DATA_SAVE_PATH}")
print("
数据预览(前5行):")
print(df[["城市", "当前气温(℃)", "年平均气温(℃)", "年平均降水量(mm)", "简化气候类型"]].head())
return df
# -------------------------- 6. 多维度数据分析 --------------------------
def analyze_climate_data(df):
"""多维度分析:统计描述、气候类型分布、温度降水相关性"""
print("
=== 气候数据统计描述 ===")
# 核心数值指标统计
stats = df[["当前气温(℃)", "年平均气温(℃)", "年平均降水量(mm)", "当前湿度(%)"]].describe()
print(stats.round(2))
print("
=== 气候类型分布 ===")
climate_count = df["简化气候类型"].value_counts()
print(climate_count)
print("
=== 温度与降水相关性 ===")
correlation = df[["年平均气温(℃)", "年平均降水量(mm)"]].corr().iloc[0, 1]
print(f"年平均气温与年降水量相关系数:{correlation:.3f}")
print("(正值表示气温越高降水越多,负值表示气温越高降水越少)")
return {
"统计描述": stats,
"气候类型分布": climate_count,
"温降相关性": correlation
}
# -------------------------- 7. 可视化生成(4类核心图表)--------------------------
def generate_climate_visualizations(df):
"""生成气候类型饼图、温度降水趋势图、全球热力图"""
# 创建2行2列子图布局
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12), dpi=100)
fig.suptitle("全球城市气候数据分析图表", fontsize=16, fontweight="bold", y=0.95)
# 图表1:气候类型分布饼图
climate_count = df["简化气候类型"].value_counts()
colors = ["#ff9f43", "#0984e3", "#6c5ce7", "#a29bfe", "#fd79a8"]
ax1.pie(
climate_count.values, labels=climate_count.index, autopct="%1.1f%%",
colors=colors[:len(climate_count)], startangle=90, textprops={"fontsize": 11}
)
ax1.set_title("全球城市气候类型分布", fontsize=14, fontweight="bold")
# 图表2:年平均气温Top10城市柱状图
top10_temp = df.nlargest(10, "年平均气温(℃)")[["城市", "年平均气温(℃)"]].sort_values("年平均气温(℃)")
ax2.barh(top10_temp["城市"], top10_temp["年平均气温(℃)"], color="#ff6b6b", alpha=0.7)
ax2.set_title("年平均气温Top10城市", fontsize=14, fontweight="bold")
ax2.set_xlabel("年平均气温(℃)")
# 添加数值标签
for i, v in enumerate(top10_temp["年平均气温(℃)"]):
ax2.text(v + 0.5, i, f"{v}℃", va="center", fontsize=10)
# 图表3:年平均气温与降水量散点图(带相关性拟合线)
sns.regplot(x="年平均气温(℃)", y="年平均降水量(mm)", data=df, ax=ax3, color="#00b894", scatter_kws={"alpha": 0.6})
ax3.set_title("年平均气温与降水量相关性", fontsize=14, fontweight="bold")
ax3.set_xlabel("年平均气温(℃)")
ax3.set_ylabel("年平均降水量(mm)")
ax3.grid(True, alpha=0.3)
# 图表4:当前气温vs年平均气温对比(前12个城市)
top12_cities = df.head(12)
x = range(len(top12_cities))
width = 0.35
ax4.bar([i - width/2 for i in x], top12_cities["当前气温(℃)"], width, label="当前气温", color="#ffa726", alpha=0.8)
ax4.bar([i + width/2 for i in x], top12_cities["年平均气温(℃)"], width, label="年平均气温", color="#42a5f5", alpha=0.8)
ax4.set_title("当前气温与年平均气温对比(前12城)", fontsize=14, fontweight="bold")
ax4.set_xlabel("城市")
ax4.set_ylabel("气温(℃)")
ax4.set_xticks(x)
ax4.set_xticklabels(top12_cities["城市"], rotation=45, ha="right")
ax4.legend()
ax4.grid(True, alpha=0.3, axis="y")
# 调整布局并保存
plt.tight_layout()
plt.savefig(f"{CHART_SAVE_PATH}.png", dpi=300, bbox_inches="tight")
plt.show()
print(f"统计图表已保存到:{CHART_SAVE_PATH}.png")
# 生成全球气候热力图(按年平均气温)
generate_heatmap(df)
def generate_heatmap(df):
"""生成全球城市年平均气温热力图(folium交互式)"""
# 初始化地图(中心设为全球中点,缩放级别2)
m = folium.Map(location=[0, 0], zoom_start=2, tiles="CartoDB positron")
# 准备热力图数据(纬度、经度、年平均气温)
heat_data = []
for _, row in df.iterrows():
if pd.notna(row["纬度"]) and pd.notna(row["经度"]) and pd.notna(row["年平均气温(℃)"]):
heat_data.append([row["纬度"], row["经度"], row["年平均气温(℃)"]])
# 添加热力图图层
HeatMap(
heat_data,
min_opacity=0.5,
max_val=df["年平均气温(℃)"].max(),
radius=15,
blur=10,
max_zoom=10
).add_to(m)
# 为每个城市添加标记点(点击显示详情)
for _, row in df.iterrows():
if pd.notna(row["纬度"]) and pd.notna(row["经度"]):
popup_html = f"""
<h4>{row['城市']}</h4>
<p>年平均气温:{row['年平均气温(℃)']}℃</p>
<p>年平均降水量:{row['年平均降水量(mm)']}mm</p>
<p>气候类型:{row['简化气候类型']}</p>
<p>当前气温:{row['当前气温(℃)']}℃</p>
"""
folium.Marker(
location=[row["纬度"], row["经度"]],
popup=folium.Popup(popup_html, max_width=300),
icon=folium.Icon(color="blue", icon="info-sign")
).add_to(m)
# 保存热力图
m.save(HEATMAP_SAVE_PATH)
print(f"全球气候热力图已保存到:{HEATMAP_SAVE_PATH}(用浏览器打开查看)")
# -------------------------- 8. 主函数(串联全流程)--------------------------
def main():
print("=== 开始全球城市气候数据定向抓取与分析 ===")
# 步骤1:获取所有目标城市的经纬度
print("
1. 获取城市经纬度...")
city_coords = [get_city_coords(city) for city in TARGET_CITIES]
city_coords = [coords for coords in city_coords if coords is not None] # 过滤失败数据
print(f"成功获取 {len(city_coords)}/{len(TARGET_CITIES)} 个城市的经纬度")
# 步骤2:抓取多源气候数据
print("
2. 抓取气候数据...")
raw_data = []
for coords in city_coords:
print(f"正在抓取 {coords['城市']}...")
# 抓取API实时数据
api_data = crawl_openweather_data(coords)
if not api_data:
continue
# 抓取历史平均数据
historical_data = crawl_climatedata_historical(coords["城市"])
# 合并数据
merged_data = {**api_data, **historical_data}
raw_data.append(merged_data)
if not raw_data:
print("未抓取到有效气候数据,程序终止")
return
# 步骤3:数据清洗与整合
print("
3. 数据清洗与整合...")
clean_df = clean_and_merge_data(raw_data)
# 步骤4:多维度数据分析
print("
4. 多维度数据分析...")
analyze_climate_data(clean_df)
# 步骤5:生成可视化图表
print("
5. 生成可视化图表...")
generate_climate_visualizations(clean_df)
print("
=== 全球城市气候数据抓取与分析全流程完成! ===")
if __name__ == "__main__":
main()
3.3 关键配置说明(按需自定义)
3.3.1 定向修改目标城市
修改 列表,支持新增/删除全球任意城市(如添加“约翰内斯堡”“温哥华”等):
TARGET_CITIES
TARGET_CITIES = ["北京", "纽约", "悉尼", "约翰内斯堡", "温哥华", "开罗"] # 自定义城市
3.3.2 调整数据/图表保存路径
DATA_SAVE_PATH = "自定义数据保存路径.csv" # 如"D:/气候数据.csv"
CHART_SAVE_PATH = "自定义图表名称" # 保存为PNG图片
HEATMAP_SAVE_PATH = "自定义热力图名称.html" # 交互式HTML文件
3.3.3 扩展数据维度
若需抓取更多指标(如日照时长、气压),可修改 函数,从API响应中提取更多字段:
crawl_openweather_data
# 新增提取日照时长(API返回的是秒,转换为小时)
sunshine_hours = current.get("sunrise", 0) # 示例,实际需根据API字段调整
merged_data["日照时长(h)"] = round(sunshine_hours / 3600, 1)
3.4 运行步骤与效果展示
3.4.1 运行代码
python global_climate_analysis.py
3.4.2 终端输出示例
=== 开始全球城市气候数据定向抓取与分析 ===
1. 获取城市经纬度...
成功获取 18/18 个城市的经纬度
2. 抓取气候数据...
正在抓取 北京...
正在抓取 上海...
...
3. 数据清洗与整合...
数据清洗完成,已保存到:全球城市气候数据.csv
数据预览(前5行):
城市 纬度 经度 ... 年平均气温(℃) 年平均降水量(mm) 简化气候类型
0 北京 39.9042 116.4074 ... 12.3 571.4 温带气候
1 上海 31.2304 121.4737 ... 16.1 1184.4 温带气候
...
4. 多维度数据分析...
=== 气候数据统计描述 ===
当前气温(℃) 年平均气温(℃) 年平均降水量(mm) 当前湿度(%)
count 18.000 18.000 18.000 18.000
mean 22.500 20.300 892.600 65.300
...
5. 生成可视化图表...
统计图表已保存到:气候数据分析图表.png
全球气候热力图已保存到:全球气候热力图.html(用浏览器打开查看)
=== 全球城市气候数据抓取与分析全流程完成! ===
3.4.3 输出文件说明
:结构化数据文件,包含所有城市的经纬度、实时气候、历史气候、气候类型等信息,可直接用Excel打开;
全球城市气候数据.csv:4合一统计图表(气候类型分布、气温Top10、温降相关性、当前vs平均气温对比);
气候数据分析图表.png:交互式热力图,用浏览器打开后可缩放、点击城市查看详情,直观展示全球气候分布。
全球气候热力图.html
四、核心技术细节与优化技巧
4.1 定向抓取优化
经纬度精准定位:通过 geopy 对接 OpenStreetMap,避免手动查询经纬度,支持全球任意城市;多源数据互补:API 保证时效性(当前/近期数据),网页抓取补充历史均值,解决单一数据源信息不全问题;失败重试机制:可在请求函数中添加重试逻辑,应对网络波动:
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# 创建带重试的session
session = requests.Session()
retry = Retry(total=3, backoff_factor=1)
session.mount("http://", HTTPAdapter(max_retries=retry))
4.2 数据清洗关键步骤
缺失值处理:按气候类型分组填充均值,比全局均值更精准(如热带气候和寒带气候均值差异大);单位统一:API 数据默认转换为摄氏温度、km/h,网页数据提取数字后标准化,避免单位混乱;气候类型简化:将复杂的柯本气候分类法简化为“热带/温带/寒带/干旱/其他”,便于分析和可视化。
4.3 可视化优化技巧
色彩搭配:用暖色调表示高温、冷色调表示低温,热力图透明度适中,避免视觉疲劳;交互性增强:folium 热力图支持缩放、点击查看详情,比静态图表更直观;标签优化:柱状图、饼图添加数值标签,散点图添加拟合线,提升图表可读性。
五、避坑指南(6个高频问题解决方案)
坑1:OpenWeatherMap API 调用失败(401/403)
原因:API 密钥无效或未生效(新注册需等待10分钟);解决:① 检查 文件中密钥是否正确;② 确认密钥已生效(可直接访问 API URL 测试);③ 避免频繁调用(免费版速率限制60次/分钟)。
.env
坑2:城市经纬度获取失败
原因:城市名拼写错误,或 geopy 访问超时;解决:① 确认城市名正确(如“里约热内卢”而非“里约”);② 更换 user_agent(避免被 OpenStreetMap 限制);③ 增加超时时间()。
timeout=20
坑3:Climate-Data 网页抓取失败(403/页面解析为空)
原因:目标网站反爬,禁止爬虫访问;解决:① 添加请求头(User-Agent、Referer);② 降低抓取频率(添加 );③ 更换 IP 代理(结合之前的代理池方案)。
time.sleep(2)
坑4:中文乱码(图表/CSV文件)
原因:编码格式不匹配;解决:① 图表设置中文字体(Windows 用 SimHei,Mac 用 Arial Unicode MS);② CSV 保存时指定 (支持Excel打开)。
encoding="utf-8-sig"
坑5:热力图无数据显示
原因:经纬度或气温数据存在缺失值;解决:① 过滤缺失经纬度的城市;② 确保 列表非空;③ 调整热力图
heat_data 和
radius 参数。
blur
坑6:数据清洗后数值为空
原因:原始数据提取失败,或转换为数值类型时出错;解决:① 检查网页抓取的标签是否正确(网站结构可能更新);② 用 强制转换,避免整体数据丢失。
pd.to_numeric(..., errors="coerce")
六、进阶扩展方向
定时更新数据:用 库设置每日抓取,自动更新气候数据和图表;存储到数据库:将清洗后的数据存入 MySQL/MongoDB,支持批量查询和历史数据对比;气候趋势预测:结合时间序列数据(如近10年气温变化),用
schedule 模型预测未来气候趋势;多指标可视化:新增日照时长、风速分布图表,或用
ARIMA 生成交互式3D图表;区域筛选功能:支持按大洲、国家筛选城市,生成针对性的区域气候分析报告。
plotly
总结
本文实现了“定向抓取→多源整合→清洗分析→可视化”的全流程,核心优势在于“全球覆盖+定向筛选+多维度分析”,既满足了科研、项目中的数据需求,也适合旅行规划等日常场景。
关键在于:通过 geopy 解决全球城市定位问题,用 API+网页抓取互补保证数据完整性,借助 pandas 和 matplotlib 降低数据分析门槛,最后用 folium 生成交互式热力图,让结果更直观。
如果在实操中遇到 API 密钥配置、网页结构更新、可视化优化等问题,可针对性交流解决方案!