Python爬虫实战:爬取天气数据并制作动态轮播图 马上就到期末了不少同学都在为 Python 课程大作业发愁。如果只是写一个“通讯录管理系统”或“图书借阅系统”既没有亮点也很难体现爬虫、数据处理、可视化这一整套技能。本文分享一个综合性强、演示效果好的 Python 爬虫期末大作业案例利用 Python 爬取天气数据并实现数据可视化最终绘制天气轮播图。整个项目会完整覆盖以下技术点使用requests发起 HTTP 请求获取天气数据接口的 JSON 内容。使用pandas对爬取到的数据进行清洗与整理。使用matplotlib绘制温度趋势图、天气分布图。使用matplotlib.animation.FuncAnimation制作动态天气轮播图。这套案例非常适合作为期末大作业也适合想系统练习“爬虫 数据可视化”的初学者。即使你的目标网站接口字段不一样也可以参考本文的解析思路花几分钟改成自己的接口即可。下面我们直接进入正题。1. 背景与核心思路1.1 这个项目解决什么问题天气查询是日常生活中非常常见的功能天气预报类 App 和网站背后都有一套完整的数据采集和展示流程。从学习角度来看天气数据很适合用来练手因为它的结构清晰、字段容易理解而且可视化出来的图表效果直观。我们在这个项目中要解决的核心问题有三个如何从互联网上获取天气数据。实际项目中一般不会直接解析网页 HTML而是请求网站背后的数据接口拿到 JSON 格式的数据再从中提取城市、日期、天气现象、最高温、最低温、风力等字段。如何对抓取到的数据进行结构化整理。原始 JSON 数据不能直接用于绘图需要转成pandas.DataFrame并处理缺失值、类型转换等问题。如何把数据用好看、动态的方式展示出来。静态图表容易实现但不是特别出彩。作为期末大作业增加一个“天气轮播图”的动态展示环节可以明显提升项目的完成度。1.2 项目整体流程整个项目的执行流程可以拆成下面几个步骤分析目标天气数据接口确认返回的 JSON 结构。编写爬虫模块对每个城市发起请求并解析数据。将多个城市的数据合并成一个 DataFrame。对数据进行清洗包括空值处理、数值类型转换等。生成静态可视化图表例如未来 7 天温度变化折线图。制作动态轮播图按城市循环展示天气信息。将最终数据保存到 CSV 文件中方便离线分析和二次使用。为了照顾不同情况本文的爬虫代码会做一个“真实接口 模拟数据兜底”的设计。如果你的网络环境无法访问目标接口或者接口结构暂时没有适配好程序会生成一组模拟天气数据保证后续的可视化流程可以正常跑通。这样交作业时就不会出现“爬虫没数据后面全空”的尴尬情况。2. 环境准备与依赖安装2.1 Python 版本与开发工具本文示例代码基于Python 3.8编写建议使用 Python 3.10 或更高版本。开发工具推荐使用PyCharm Community Edition 或 Professional Edition。VS Code 配合 Python 插件。如果你还没有安装 Python可以去 Python 官网下载安装包。安装时需要注意勾选Add Python to PATH否则后续在命令行执行pip会提示找不到命令。2.2 安装第三方依赖库项目需要用到以下第三方库库名主要用途requests发送 HTTP 请求获取天气接口数据pandas数据清洗、合并、类型转换matplotlib绘制静态图表和动态轮播图使用以下命令一次性安装pip install requests pandas matplotlib如果你的环境中存在多个 Python 版本可能需要使用python -m pip install requests pandas matplotlib安装完成后可以打开 Python 交互环境验证一下python -c import requests, pandas, matplotlib; print(依赖安装成功)如果能正常输出依赖安装成功说明环境已经准备就绪。2.3 项目目录结构为了让代码结构清晰建议按下面的目录组织项目weather_project/ ├── main.py # 主程序入口串联整个流程 ├── weather_spider.py # 爬虫模块请求数据、解析数据 ├── weather_analysis.py # 数据处理与可视化模块 ├── requirements.txt # 依赖清单 └── data/ └── weather_data.csv # 爬取结果保存目录实际操作时可以按照自己的习惯调整文件名称但建议把爬虫、数据处理、可视化分离成不同模块这样代码可读性更高也方便在答辩时讲解。3. 天气数据爬取模块爬虫模块是整个项目的数据来源。这一节先介绍接口分析的思路再给出完整的请求与解析代码。3.1 如何找到天气数据接口很多同学一提到爬虫就想到去解析 HTML但直接用BeautifulSoup解析页面不但效率低而且很容易被页面结构调整影响。更推荐的方式是使用浏览器开发者工具F12在 Network 面板中找到 XHR 请求从中筛选返回 JSON 的接口。以常见的天气网站为例打开开发者工具后切换到 Network 面板刷新页面再筛选XHR或Fetch/XHR往往可以找到一个类似weather?cityxxx的接口。点击该请求在 Preview 或 Response 中可以看到返回的 JSON 数据里面通常包含{ city: 北京, daily: [ { date: 2025-06-01, weather: 晴, temp_max: 32, temp_min: 22, wind: 3级 } ] }这里需要特别说明不同网站、不同接口的字段名称不同有的可能是high/low有的可能是tmp_max/tmp_min。本文为了让示例具备通用性会把“字段映射关系”单独提取出来方便你根据自己的接口结构做调整。3.2 requests 请求封装下面编写weather_spider.py核心类为WeatherSpider。 模块说明天气数据爬虫模块 负责发起 HTTP 请求、解析 JSON 数据并在请求失败时回退到模拟数据 import random import datetime import requests # 字段映射如果你的目标接口字段名不同只需要修改这个字典即可 FIELD_MAP { city: city, # 城市名字段 date: date, # 日期字段 weather: weather, # 天气现象字段 temp_max: temp_max, # 最高温字段 temp_min: temp_min, # 最低温字段 wind: wind # 风力字段 } class WeatherSpider: def __init__(self, api_url, field_mapNone, headersNone): self.api_url api_url self.field_map field_map if field_map else FIELD_MAP self.headers headers if headers else { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } def fetch(self): 发送 GET 请求返回 JSON 数据。 如果请求失败返回 None由上层决定是否使用模拟数据。 try: resp requests.get(self.api_url, headersself.headers, timeout10) resp.raise_for_status() return resp.json() except Exception as e: print(f[WARN] 请求 {self.api_url} 失败{e}) return None def parse(self, data): 将接口返回的 JSON 数据解析成统一格式的列表。 每一条记录是一个字典包含 city、date、weather、temp_max、temp_min、wind。 if not data: return [] # 兼容两种常见结构{daily: [...]} 或 {data: [...]} daily_list data.get(daily, data.get(data, [])) # 如果 data 本身是 dict并且里面还有一个 daily 字段就继续向下取 if isinstance(daily_list, dict): daily_list daily_list.get(daily, []) records [] city data.get(self.field_map[city], 未知城市) for item in daily_list: record { city: city, date: item.get(self.field_map[date]), weather: item.get(self.field_map[weather]), temp_max: item.get(self.field_map[temp_max]), temp_min: item.get(self.field_map[temp_min]), wind: item.get(self.field_map[wind]), } records.append(record) return records def generate_demo_data(city, days7): 生成模拟天气数据。 当真实接口不可用时使用随机数据兜底保证可视化流程可以正常运行。 weather_types [晴, 多云, 阴, 小雨, 中雨, 雷阵雨] wind_levels [1级, 2级, 3级, 4级] records [] today datetime.date.today() for i in range(days): date today datetime.timedelta(daysi) weather random.choice(weather_types) # 让最低温在 15~26 之间最高温在此基础上加 6~12 度 temp_low random.randint(15, 26) temp_high temp_low random.randint(6, 12) wind random.choice(wind_levels) records.append({ city: city, date: str(date), weather: weather, temp_max: temp_high, temp_min: temp_low, wind: wind, }) return records def run_spider(city, api_url): 对外暴露的爬虫入口。 先请求真实接口失败则返回模拟数据。 spider WeatherSpider(api_url.format(citycity)) data spider.fetch() if data is None: print(f[INFO] 使用模拟数据{city}) return generate_demo_data(city) records spider.parse(data) # 如果解析结果为空也回退到模拟数据 if not records: print(f[WARN] 解析数据为空使用模拟数据{city}) return generate_demo_data(city) return records这段代码中需要重点说明几个设计点FIELD_MAP是字段映射字典。你在实际使用中如果发现接口返回的字段叫high和low只需要把temp_max和temp_min对应的值改成high和low即可。fetch中捕获了所有异常避免因为某一个城市的接口异常而中断整个程序。generate_demo_data生成的是未来 7 天的模拟数据这样即使没有真实接口后续的可视化代码也可以完整演示。3.3 测试爬虫模块可以写一个简单的测试脚本验证爬虫模块能正常返回数据# 测试 weather_spider.py if __name__ __main__: # 示例接口请替换成你实际抓取到的天气接口地址 api_url https://example.com/weather?city{city} result run_spider(北京, api_url) print(result[:2])如果真实接口不可用控制台会输出[WARN] 请求 https://example.com/weather?city北京 失败... [INFO] 使用模拟数据北京 [{city: 北京, date: 2025-..., weather: 晴, temp_max: 34, temp_min: 25, wind: 2级}, ...]到这里数据获取部分就完成了。4. 数据清洗与结构化整理爬虫返回的是 Python 字典列表虽然结构清晰但还不能直接用于绘图。我们需要把数据转成pandas.DataFrame并进行一系列清洗操作。4.1 将数据转换为 DataFrame创建一个新的函数放在weather_analysis.py中 模块说明数据处理与可视化模块 负责数据清洗、静态图表绘制、动态轮播图制作 import pandas as pd def clean_data(records): 将字典列表转换为 DataFrame并完成基础清洗 1. 温度字段转为数值类型 2. 删除日期为空或温度异常的行 3. 按城市和日期排序 df pd.DataFrame(records) # 如果传入的数据为空直接返回空 DataFrame if df.empty: print([WARN] 输入数据为空请检查爬虫模块) return df # 温度转数值无法转换的会变成 NaN df[temp_max] pd.to_numeric(df[temp_max], errorscoerce) df[temp_min] pd.to_numeric(df[temp_min], errorscoerce) # 删除关键字段缺失的行 df df.dropna(subset[date, temp_max, temp_min]) # 排序让日期在同一个城市内是从小到大排列 df df.sort_values([city, date], ascending[True, True]) # 重置索引避免排序后索引不连续 df df.reset_index(dropTrue) return df4.2 保存数据到 CSV为了方便后续离线分析建议把清洗后的数据保存下来。CSV 文件使用utf-8-sig编码这样可以避免用 Excel 打开时出现中文乱码。def save_data(df, file_pathdata/weather_data.csv): 将 DataFrame 保存为 CSV 文件 import os # 如果 data 目录不存在则自动创建 os.makedirs(os.path.dirname(file_path), exist_okTrue) df.to_csv(file_path, indexFalse, encodingutf-8-sig) print(f[INFO] 数据已保存到{file_path})4.3 验证清洗效果写一段测试代码来看清洗效果if __name__ __main__: demo_records [ {city: 北京, date: 2025-06-01, weather: 晴, temp_max: 32, temp_min: 22, wind: 2级}, {city: 北京, date: 2025-06-02, weather: 多云, temp_max: 30, temp_min: 20, wind: 3级}, {city: 北京, date: 2025-06-03, weather: 小雨, temp_max: None, temp_min: 18, wind: 2级}, ] df clean_data(demo_records) print(df)输出结果中日期为2025-06-03的这一行因为最高温缺失会被删除剩下的两行数据温度字段已经从字符串变成了数值类型。5. 天气数据静态可视化数据清洗完成之后就可以开始可视化了。静态图表虽然简单但它是动态轮播图的基础。我们先实现两个常用图表。5.1 设置中文字体使用matplotlib绘图时新手最常见的坑是中文乱码。这是因为matplotlib默认字体是不支持中文的需要手动设置。import matplotlib.pyplot as plt # 设置中文字体Windows 通常为 SimHeimacOS 可尝试 PingFang SCLinux 可尝试 WenQuanYi Zen Hei plt.rcParams[font.sans-serif] [SimHei] # 解决负号显示异常的问题 plt.rcParams[axes.unicode_minus] False如果不是 Windows 系统可以在本地执行下面这段代码查看当前系统支持的字体import matplotlib.font_manager as fm fonts [f.name for f in fm.fontManager.ttflist] for f in sorted(set(fonts)): print(f)然后把plt.rcParams[font.sans-serif]改成列表中存在的某个中文字体名称。5.2 绘制未来 7 天温度趋势图温度趋势图是天气类可视化最常见的图它用两条折线展示最高温和最低温的变化。def plot_temperature_trend(df, city北京): 绘制单个城市未来 7 天的温度趋势折线图 city_df df[df[city] city].sort_values(date) plt.figure(figsize(10, 6)) plt.plot(city_df[date], city_df[temp_max], label最高温, markero, colorcoral, linewidth2) plt.plot(city_df[date], city_df[temp_min], label最低温, markers, colorsteelblue, linewidth2) # 在折线图上方标注天气现象 for i, row in city_df.iterrows(): plt.annotate(row[weather], (row[date], row[temp_max]), textcoordsoffset points, xytext(0, 12), hacenter, fontsize10) plt.title(f{city} 未来 {len(city_df)} 天温度趋势, fontsize14) plt.xlabel(日期) plt.ylabel(温度℃) plt.legend() plt.grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.show()这个方法中有几个细节city_df[date]作为 x 轴刻度如果日期太多可以旋转角度避免重叠。plt.annotate把天气现象标注在最高温折线的上方让信息更完整。plt.tight_layout()自动调整布局避免标题或标签被裁剪。5.3 绘制天气分布柱状图除了温度趋势我们也可以统计某段时间内各种天气现象出现的次数用柱状图展示。def plot_weather_distribution(df): 统计所有城市中各种天气现象的出现次数绘制柱状图 weather_counts df[weather].value_counts() plt.figure(figsize(8, 5)) weather_counts.plot(kindbar, colorskyblue, edgecolorblack) plt.title(各天气现象出现次数, fontsize14) plt.xlabel(天气) plt.ylabel(次数) plt.xticks(rotation45) plt.grid(axisy, linestyle--, alpha0.5) plt.tight_layout() plt.show()如果数据中只有“晴”和“多云”柱状图就只有两根柱子。为了方便演示可以在爬虫阶段多爬几个城市这样天气现象会更丰富。6. 动态天气轮播图制作动态轮播图是本文的特色部分。大部分期末作业只会输出静态图表如果能用matplotlib.animation展示一个动态切换城市的天气看板项目会更有亮点。6.1 FuncAnimation 的核心逻辑matplotlib.animation.FuncAnimation的基本用法是from matplotlib.animation import FuncAnimation def update(frame): # 每一帧要做的事 pass anim FuncAnimation(fig, update, frames数量, interval毫秒, repeatTrue)其中fig是画布对象。update是每一帧都会回调的函数。frames决定总共有多少帧。interval是每帧之间的间隔时间单位毫秒。repeatTrue表示动画播放完一轮后重新开始。我们可以让每一帧展示一个不同城市的天气情况这样就形成了“轮播图”的效果。6.2 单城市天气卡片绘制先实现一个函数绘制单个城市的天气卡片供每一帧复用。def draw_city_weather(ax, city_df): 在指定坐标轴 ax 上绘制一个城市的天气信息卡片 ax.clear() # 取出城市名称 city_name city_df[city].iloc[0] x range(len(city_df)) # 画温度折线 ax.plot(x, city_df[temp_max], label最高温, markero, colorcoral, linewidth2) ax.plot(x, city_df[temp_min], label最低温, markers, colorsteelblue, linewidth2) # 设置 x 轴刻度为日期 ax.set_xticks(list(x)) ax.set_xticklabels(city_df[date], rotation45, haright) # 在最高温点上方标注天气现象 for i, row in city_df.iterrows(): ax.annotate(f{row[weather]}\n{row[temp_max]}℃, (i, row[temp_max]), textcoordsoffset points, xytext(0, 12), hacenter, fontsize9) ax.set_title(f{city_name} 未来天气轮播, fontsize15) ax.set_ylabel(温度℃) ax.legend(locupper right) ax.grid(True, linestyle--, alpha0.4)6.3 多城市动态轮播现在编写动画主函数。将清洗后的 DataFrame 按照城市分组每一帧展示一个城市。from matplotlib.animation import FuncAnimation def plot_weather_rotation(df, interval1500): 绘制天气轮播图动画 df: 包含多个城市数据的 DataFrame interval: 帧间隔毫秒数 返回 anim 对象 # 按照城市分组并转成列表方便按帧索引 city_groups [] for city, group in df.groupby(city): group group.sort_values(date) city_groups.append((city, group)) # 创建画布 fig, ax plt.subplots(figsize(10, 6)) def update(frame): city_name, city_df city_groups[frame] draw_city_weather(ax, city_df) ax.set_title(f{city_name} 未来 {len(city_df)} 天天气轮播, fontsize15) anim FuncAnimation( fig, update, frameslen(city_groups), intervalinterval, repeatTrue ) return anim调用方式anim plot_weather_rotation(df, interval1200) # 保存为 GIF 动图方便放进 PPT 或实验报告 anim.save(weather_rotation.gif, writerpillow, fps1) # 打开窗口查看动态效果 plt.show()这里需要说明interval和fps会同时影响播放速度。在plt.show()中生效的是interval而在anim.save()中更关键的是fps。fps1表示每秒播放 1 帧如果觉得太慢可以改成fps1.5或fps2。6.4 轮播图效果说明运行后的轮播图效果是画布上依次展示北京、上海、广州、成都、西安等城市的未来 7 天天气折线图。每切换一个城市标题中的城市名也会跟着变化最高温和最低温的折线、天气标注都会动态刷新。如果保存成 GIF可以直接在期末答辩的 PPT 中播放效果非常直观。7. 完整代码整合与运行验证前面的代码是按模块拆分讲解的这一节我们写一个main.py把整个流程串起来。7.1 编写 main.py 主程序入口爬取天气数据 - 数据清洗 - 静态可视化 - 动态轮播图 from weather_spider import run_spider from weather_analysis import clean_data, save_data from weather_analysis import plot_temperature_trend, plot_weather_distribution from weather_analysis import plot_weather_rotation def main(): # 1. 配置需要爬取的城市列表 cities [北京, 上海, 广州, 成都, 西安] # 2. 配置真实天气接口地址{} 会被替换成城市名 # 如果无法访问会自动回退到模拟数据不影响后续演示 api_url https://example.com/weather?city{city} # 3. 循环爬取每个城市的数据 all_records [] for city in cities: print(f[INFO] 正在处理城市{city}) records run_spider(city, api_url) all_records.extend(records) # 4. 数据清洗 df clean_data(all_records) if df.empty: print([ERROR] 清洗后没有可用数据程序终止) return # 5. 保存数据到 CSV save_data(df, data/weather_data.csv) # 6. 静态可视化绘制北京的 7 天温度趋势 plot_temperature_trend(df, city北京) # 7. 静态可视化天气现象分布柱状图 plot_weather_distribution(df) # 8. 动态轮播图所有城市轮播展示 anim plot_weather_rotation(df, interval1500) # 9. 保存 GIF 动图 anim.save(weather_rotation.gif, writerpillow, fps1) print([INFO] 动态轮播图已保存weather_rotation.gif) # 10. 在窗口中播放动画 plt.show() if __name__ __main__: main()注意plot_weather_rotation返回的是动画对象为了在main()中引用需要把plot_weather_rotation在weather_analysis.py中定义并导出。同时plt.show()会阻塞程序所以 GIF 保存动作要放在plt.show()之前。7.2 运行命令在项目根目录执行python main.py预期输出大致如下[INFO] 正在处理城市北京 [WARN] 请求 https://example.com/weather?city北京 失败... [INFO] 使用模拟数据北京 [INFO] 正在处理城市上海 [INFO] 使用模拟数据上海 ... [INFO] 数据已保存到data/weather_data.csv [INFO] 动态轮播图已保存weather_rotation.gif随后会弹出静态图窗口和动态轮播窗口。如果不想看到弹窗可以注释掉plt.show()只保留 GIF 保存功能。7.3 运行结果说明项目运行结束后你会得到以下产物data/weather_data.csv所有城市的天气数据可以用 Excel 打开查看。weather_rotation.gif动态轮播图可以直接嵌入到期末报告或答辩 PPT。两个静态图窗口温度趋势图和天气分布图关闭窗口后程序结束。如果运行过程中弹出了图表窗口但程序不结束这是正常的。因为plt.show()会阻塞程序直到窗口被关闭。8. 常见问题与排查思路在写爬虫和可视化代码时新手经常会遇到下面几个问题。这里整理成表格方便快速排查。问题现象常见原因解决思路程序只显示 exit code 0没有任何输出没有调用main()或代码中没有print语句检查if __name__ __main__:入口爬虫请求报错无法获取数据接口地址错误、网络不可用、接口有反爬先用浏览器访问接口确认是否返回 JSON设置 User-Agent图表中文显示为方块matplotlib默认字体不支持中文设置plt.rcParams[font.sans-serif] [SimHei]保存 GIF 失败缺少 Pillow 库执行pip install pillow爬虫返回的数据为空接口字段名和代码不一致或数据结构嵌套不同打印接口原始 JSON调整FIELD_MAP映射折线图 x 轴日期堆叠在一起日期过长、没有旋转设置plt.xticks(rotation45)动画不刷新每帧都创建了新坐标轴或没有调用ax.clear()在update中先ax.clear()再绘图8.1 关于 exit code 0 但没有输出这是 PyCharm 中非常典型的问题。很多同学写的 Python 脚本只有函数定义没有调用入口所以程序运行后直接结束输出面板只有一行Process finished with exit code 0解决办法是在文件末尾加上if __name__ __main__: main()或者在main.py中直接调用main()。另外如果你希望在控制台看到更多调试信息可以在关键位置加入print例如print(f当前共获取 {len(records)} 条天气记录)8.2 爬虫请求被拒绝怎么办部分天气接口对请求头比较敏感如果直接使用默认的requests请求可能会返回 403 或直接拒绝连接。解决方案是设置User-Agent模拟真实浏览器的请求。如果仍然不行可以增加Referer字段。请求头示例headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Referer: https://example.com/, Accept: application/json, text/plain, */* }需要注意的是抓取数据时要遵守目标网站的访问规则不要高频请求也不要抓取需要登录或非公开的接口。做期末作业时优先选择公开、免费的天气接口即可。8.3 如何确定接口返回的字段名在浏览器开发者工具中找到天气接口后点击 Preview 标签页可以看到接口返回的完整 JSON。找到每天的数据查看里面有哪些字段。如果接口返回的是{ date: 2025-06-01, day: 晴天, high: 32, low: 22 }那么你的FIELD_MAP应该改成FIELD_MAP { city: city, date: date, weather: day, temp_max: high, temp_min: low, wind: wind }代码中用item.get(self.field_map[temp_max])来取值这样即使字段名不同也能适配。9. 最佳实践与工程建议写完一个能运行的期末大作业不算难但要想在答辩时经得起提问还是在代码里体现一些工程化意识下面给出几点建议。9.1 爬虫请求规范不要一个循环把几个城市的请求瞬间发出去这样很容易触发反爬。建议每次请求之间随机休眠一小段时间import time import random for city in cities: records run_spider(city, api_url) all_records.extend(records) time.sleep(random.uniform(0.5, 1.5))同时在代码注释中明确标注数据来源和请求频率体现“合法爬取、合理使用”的意识。9.2 数据落盘与离线分析爬取下来的数据应该保存到本地文件这样即使后续网络不可用也能基于已有的 CSV 数据继续分析和绘图。本文已经通过save_data实现了这一功能。你可以进一步扩展判断 CSV 文件是否存在如果存在就优先读取本地数据减少对接口的请求次数。import os if os.path.exists(data/weather_data.csv): df pd.read_csv(data/weather_data.csv) else: # 执行爬虫流程 pass9.3 代码模块化设计把爬虫、数据清洗、可视化拆分成不同模块不只是为了让代码好看更重要的是方便测试和维护。你在答辩时可以说weather_spider.py只负责数据采集不关心后面如何绘图。weather_analysis.py只负责数据处理和可视化不关心数据是从哪里来的。main.py负责串联整个流程。这种分层思想在很多真实项目中都能用到平时练习时养成好习惯面试和做项目都会更有底气。9.4 可视化效果优化在期末答辩中图表的美观程度直接影响老师的第一印象。下面几个小技巧可以让图表质量更高使用协调的颜色搭配比如最高温用暖色、最低温用冷色。给图表加上标题、坐标轴标签、图例和数据标注。在折线图上标注具体数值或天气现象增加信息量。把图表尺寸调大避免文字挤在一起。使用plt.tight_layout()自动调整布局。9.5 合理扩展项目方向如果想让这个项目更进一步可以考虑以下方向接入更多城市例如爬取全国 20 个主要城市的天气数据分析南北方温差差异。增加历史数据对比爬取历史同期天气绘制“今年 vs 去年”的温度对比图。定时自动爬取使用schedule库或 Python 定时任务每天自动更新天气数据。结合 Web 展示用 Flask 搭建一个简单页面在网页上展示天气图表和轮播图。加入数据报告将统计结果生成 Word 或 PDF 报告自动输出每周天气总结。10. 总结与动手建议到这里一个完整的“Python 爬取天气数据 数据可视化 天气轮播图”项目就全部讲解完毕了。我们从接口分析开始完成了请求发送、JSON 解析、数据清洗、静态图表绘制最后通过FuncAnimation实现了多城市天气动态轮播图并且保存成了 GIF 文件。这个项目覆盖了爬虫、数据分析、可视化三大方向非常适合作为期末大作业。建议你拿到代码后按照以下顺序操作先直接运行main.py确认模拟数据流程可以跑通。再通过浏览器开发者工具找到真实的天气接口替换api_url和FIELD_MAP。最后根据自己的需求调整城市列表、图表颜色和 GIF 播放速度。如果你在运行过程中遇到了其他问题欢迎在评论区留言交流。如果这篇文章对你有帮助可以收藏备用也欢迎分享给身边正在为 Python 期末大作业发愁的同学。