Python爬取全年天气数据实战:从采集到可视化 1. 项目概述爬取全年天气数据的价值与应用场景天气数据看似平常却是城市管理、农业规划、商业决策的重要依据。去年我帮本地农场主分析历史天气时发现连续三年的春季降雨模式变化直接影响了他的播种时间选择。这个项目将带你用Python完整实现从数据采集到分析可视化的全流程掌握真实场景下的数据获取与处理能力。爬取公开天气数据的关键在于平衡效率与合法性。我们选择中国天气网作为数据源其robots.txt文件允许合理频率的爬取通常建议间隔10秒以上。这个项目特别适合以下场景个人学习Python爬虫与数据分析的完整案例商业分析中需要历史天气数据作为参考依据学术研究中的气候模式分析基础数据准备2. 技术选型与工具准备2.1 核心工具链组成经过多个项目的实践验证我固定使用这套稳定组合爬虫层Requests BeautifulSoup4静态页面 / Selenium动态渲染数据存储SQLite轻量 / MySQL团队协作分析处理Pandas NumPy可视化Matplotlib基础图表 Pyecharts交互图表提示新手常犯的错误是过早引入Scrapy等框架。对于定向爬取单一网站的中小规模数据轻量级组合更易调试和维护。2.2 环境配置要点在VSCode中创建Python环境时建议使用独立的虚拟环境python -m venv weather_venv source weather_venv/bin/activate # Linux/Mac weather_venv\Scripts\activate # Windows pip install requests beautifulsoup4 pandas matplotlib pyecharts如果遇到SSL证书错误常见于Windows需要额外执行pip install python-certifi-win323. 网站分析与爬虫设计3.1 目标页面结构解析以北京天气为例中国天气网的URL模式为http://www.weather.com.cn/weather1d/101010100.shtml # 当日 http://www.weather.com.cn/weather/101010100.shtml # 7天 http://www.weather.com.cn/weather40d/101010100.shtml # 40天通过开发者工具F12分析发现城市ID是关键参数如101010100代表北京数据包裹在script标签中的JSON格式字符串里历史数据需要模拟月份选择操作3.2 爬虫核心代码实现import requests from bs4 import BeautifulSoup import json import time def get_daily_weather(city_id, year): base_url fhttp://d1.weather.com.cn/calendar_new/{year}/{city_id}_{year}{month:02d}.html headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: http://www.weather.com.cn/ } all_data [] for month in range(1, 13): try: url base_url.format(monthmonth) resp requests.get(url, headersheaders) resp.encoding utf-8 # 提取JSON数据部分 json_str resp.text.split()[1].strip() month_data json.loads(json_str) all_data.extend(month_data) time.sleep(15) # 遵守爬取间隔要求 except Exception as e: print(f获取{year}年{month}月数据失败{str(e)}) return pd.DataFrame(all_data)关键技巧中国天气网的反爬机制会检查Referer和User-Agent缺少这些头部信息将返回403错误。4. 数据清洗与结构化处理4.1 原始数据问题诊断爬取的原始数据常见问题包括温度字段包含符号如℃天气现象使用中文描述需分类编码缺失值标记为无或空字符串日期格式不统一4.2 高效清洗方案使用Pandas进行数据清洗的典型流程def clean_weather_data(df): # 温度处理 df[high_temp] df[hmax].str.replace(℃, ).astype(float) df[low_temp] df[hmin].str.replace(℃, ).astype(float) # 天气现象分类 weather_map { 晴: sunny, 多云: cloudy, 阴: overcast, 雨: rain, 雪: snow } df[weather_code] df[weather].map(weather_map) # 日期转换 df[date] pd.to_datetime(df[date], format%Y%m%d) # 风速处理 df[wind_speed] df[wind].str.extract((\d)级).astype(float) return df.dropna()5. 可视化分析与业务洞察5.1 基础温度趋势分析使用Matplotlib绘制整年温度变化import matplotlib.pyplot as plt plt.figure(figsize(12, 6)) plt.plot(df[date], df[high_temp], r-, label最高气温) plt.plot(df[date], df[low_temp], b-, label最低气温) plt.fill_between(df[date], df[high_temp], df[low_temp], coloryellow, alpha0.2) plt.title(f{year}年温度变化趋势) plt.xlabel(日期) plt.ylabel(温度(℃)) plt.legend() plt.grid() plt.show()5.2 高级可视化Pyecharts日历图更直观的全年天气分布展示from pyecharts import options as opts from pyecharts.charts import Calendar calendar ( Calendar() .add(最高温度, [list([str(d.date()), t]) for d,t in zip(df[date], df[high_temp])], calendar_optsopts.CalendarOpts(range_str(year)), ) .set_global_opts( visualmap_optsopts.VisualMapOpts( max_40, min_-10, orienthorizontal, is_piecewiseTrue ) ) ) calendar.render(temperature_calendar.html)6. 实战经验与避坑指南6.1 爬虫稳定性保障IP被封解决方案使用time.sleep(random.uniform(10, 20))模拟人工间隔搭建简单的代理IP池免费方案https://www.free-proxy-list.net/数据补全技巧# 用前后三天平均值填补缺失温度 df[high_temp] df[high_temp].fillna( df[high_temp].rolling(3, min_periods1, centerTrue).mean() )6.2 性能优化方案当处理多城市多年份数据时使用concurrent.futures.ThreadPoolExecutor实现并发爬取将数据按城市分表存储建立数据采集日志系统记录成功/失败的请求from concurrent.futures import ThreadPoolExecutor def multi_city_crawl(city_ids, years): with ThreadPoolExecutor(max_workers3) as executor: # 控制并发数 futures [] for city in city_ids: for year in years: futures.append(executor.submit(get_daily_weather, city, year)) results [f.result() for f in futures] return pd.concat(results)7. 数据分析的延伸应用7.1 商业价值挖掘案例某连锁超市通过分析发现当连续3天气温高于30℃时冰淇淋销量增长120%降雨量与外卖订单量相关系数达0.78基于这些洞察他们优化了库存调配策略7.2 气象研究基础模型构建简单的气温预测模型from sklearn.ensemble import RandomForestRegressor # 特征工程 df[day_of_year] df[date].dt.dayofyear df[month_sin] np.sin(2 * np.pi * df[date].dt.month/12) # 训练测试拆分 X df[[day_of_year, month_sin]] y df[high_temp] model RandomForestRegressor().fit(X[:-30], y[:-30]) # 用前N-30天预测最后30天这个项目最让我惊喜的是通过持续收集数据三年后这些数据成为了研究城市热岛效应的宝贵素材。建议定期运行爬虫积累数据集未来可能产生意想不到的价值。