☰
Python爬虫实战:爬取天气数据并完成可视化分析
2026/10/16 8:22:48 网站建设 项目流程

简介:本资源是一份面向计算机及相关专业本科生的Python期末大作业完整方案,聚焦网络爬虫与数据可视化实战,适用于课程设计、毕业设计参考及项目能力提升。项目基于Python实现天气数据自动化采集、清洗与多维度可视化分析,配套详实的大作业报告(含需求分析、技术选型、代码说明与结果展示),经导师指导并获98分高分评价。压缩包共514个文件,约22.33MB,包含大量SVG图表文件(用于动态可视化渲染)、HTML/CSS/JS前端页面(含keshihua.html等交互式看板)、Python核心脚本、SQL数据库文件及项目文档(如README.md、结课报告.docx),结构清晰、模块分明,便于学习者理解前后端协同逻辑。目前已有383人下载学习,所有源码均经本地编译调试可直接运行,附带完整环境配置说明与常见问题排错提示,是兼具教学规范性与工程实践性的优质学习材料。 做 Python 大作业选什么题目?我个人的答案是:只要能把“爬虫 + 数据处理 + 可视化 + 报告”这条链路完整跑通,就是最稳的选择。天气数据正好卡在这个点上——公开可访问、结构规律、字段丰富,还能做出漂亮的图表,报告也好写。这篇文章就围绕“基于 Python 的网络爬虫爬取天气数据及可视化分析”这个课程项目,把从选型、爬虫设计、数据清洗、可视化到报告撰写的完整思路和代码细节摊开讲清楚。如果你是正在为期末大作业发愁的学生,或者想用一个小项目快速掌握 Python 爬虫和数据可视化的入门操作,这篇文章可以直接当参考模板用。

我带的学弟学妹里,至少有三分之一的人第一门综合实训选了这个方向。原因很简单:天气数据不像电商数据那样反爬严格,也不像社交数据那样涉及隐私,数据量级对个人电脑完全友好,而且可视化结果一说出来人人都能看懂。更重要的是,它天然包含“从网络获取数据 → 处理数据 → 呈现结论”的完整流程,正是老师想看到的“解决实际问题的能力证明”。但很多同学交上来的作业代码就三五十行,爬完存个 Excel,画两张柱状图就完事,深度不够,答辩时很容易被问住。这次我按一个能拿高分的标准把整个项目拆开,每个环节都会解释为什么这么做,以及不这么做会踩什么坑。

1. 项目整体设计与技术选型思路

1.1 为什么选天气数据作为爬虫大作业

选项目题目其实比写代码更重要。我当时给学弟们的筛选标准是三条:数据是否容易获取、数据质量是否稳定、可视化结论是否直观。天气数据在这三点上几乎是完美匹配。目标网站公开可访问,不需要登录,不需要复杂的加密参数,返回的 HTML 结构也比较规整,对刚接触爬虫的同学来说,难度曲线刚好。对比一下其他常见方向:电商商品信息反爬严重,动不动就出现验证码;招聘网站数据是 JavaScript 动态加载,初级爬虫很难直接抓到;影视数据虽然好爬,但可视化做不出太多花样。天气数据则不同,最高温度、最低温度、天气现象、风力风向、降水情况,每个字段都能对应一种图表,报告里根本不愁没内容写。

另外从课程角度说,这类项目避开了“爬虫是否合规”的敏感地带。爬取公开的、非商业和非隐私数据用于学习研究,本身是安全的,但也要注意控制请求频率,别给目标服务器造成压力。这一点在报告里体现出来,反而是加分项,说明你有职业素养。

1.2 技术栈选型及理由

这个项目的技术栈非常固定,但选择背后的逻辑值得说清楚。

  • requests:发起 HTTP 请求。它是 Python 生态里最常用的请求库,相比 urllib 更加简洁,能够自动处理编码、会话、请求头,代码可读性好很多。
  • BeautifulSoup4:解析 HTML 文档。对于静态网页,bs4 是个非常友好的选择,它能把 HTML 转成一棵可遍历的树,用 find/find_all 就能提取出标签内容,学习成本很低。相比正则表达式硬抠文本,bs4 更不容易出错。
  • pandas:数据清洗和表格处理。天气数据量不大,但字段多、格式杂,用 pandas 处理后能非常高效地完成去重、缺失值填充和数据类型转换。
  • matplotlib:可视化。尽管 pyecharts 画出来的图更好看,但 matplotlib 胜在稳定、可控、无需额外依赖,而且写进大作业报告里的图片一般也是静态图为主,所以选它最省心。

为什么不选 Scrapy?Scrapy 确实是工业级的爬虫框架,有自己的调度器、下载器、中间件,但对一个课程大作业来说,它的架构复杂度远远超出了需求。用 Scrapy 写一个爬虫,你需要理解 Spiders、Items、Pipelines 等一系列概念,如果本身对爬虫还不熟,很容易为了用框架而用框架,反而把时间浪费在不必要的配置上。requests + bs4 的组合恰好覆盖了作业中 90% 的需求,代码量也更好控制,适合在报告中逐行讲解。

为什么不把数据存进数据库?有人会觉得用 SQLite 或 MySQL 显得更高级。但天气数据不过几百行到几千行,存 CSV 文件完全够用,而且 CSV 可以直接用 pandas 读取,对老师检查代码也更友好。如果你想展示数据库能力,可以在报告里加一句“后续可扩展为数据库存储”,但不要在没有明确需求的情况下增加复杂度。

1.3 整体实现流程

整个项目的执行链路大致分为五步:

  1. 分析目标网站页面结构,确定 URL 规律和数据字段在 HTML 中的位置。
  2. 使用 requests 携带合适的请求头访问页面,拿到 HTML 文本。
  3. 使用 BeautifulSoup 解析 HTML,提取需要的数据字段,比如日期、最高气温、最低气温、天气、风力等。
  4. 将数据整理成表格格式,用 pandas 保存为 CSV 文件。
  5. 读取 CSV,做数据清洗和预处理,再用 matplotlib 绘制多张图表,分析天气变化规律。

严格来说,完整的大作业还要加上第 6 步:把分析结论写成报告,插入图表并附上源码说明。这一点在后面的章节中单独展开。

2. 爬虫模块:把天气数据稳定地抓下来

2.1 目标分析与 URL 构造

写爬虫第一步永远是“分析页面”,不是马上写代码。打开目标天气网站,找到你要爬取的城市天气页面。这类页面的 URL 一般有固定规律,例如城市的 ID 会体现在路径或查询参数中。通过观察几个不同城市的 URL,可以总结出规律,后续只要替换城市 ID,就能复用到任意城市。

这里要特别强调:实际爬取之前,先确认目标页面是静态渲染还是动态渲染。在浏览器中右键选择“查看网页源代码”,如果能直接看到天气数据文本,说明是静态网页,用 requests 拿到的 HTML 里就包含数据,可以用 BeautifulSoup 直接解析。如果源代码里只有一堆 JavaScript,而数据是后续异步加载的,那么直接用 requests 是抓不到数据的。天气类网站一般是静态居多,但也会有一部分数据放在接口里,这种情况可以在开发者工具的 Network 面板中找 JSON 接口,同样用 requests 获取后按字典处理即可。

拿到网页之后,用开发者工具的元素选择器查看天气数据所在的 HTML 结构。基本上每条天气记录都会包含在一个列表项标签中,下面有日期节点、温度节点、天气节点和风力节点,各节点的 class 名称一般能直接看出含义。你需要把每个字段对应的选择器准确记下来,这是整个爬虫最核心的功课。

2.2 请求头伪装与反爬规避

网站的服务器会检查请求的 User-Agent,如果发现是爬虫默认的 Python-requests 标识,很可能直接拒绝响应。最简单的解决方法就是手动设置一个常见的浏览器 User-Agent。我在项目里通常还会加上 Referer 和 Accept-Language,这样请求更像真实用户。

除了请求头,请求频率同样需要控制。在循环遍历多个城市或多页数据时,每一轮请求后加一个time.sleep(random.uniform(1, 3))的小延迟,模拟人的操作节奏。这既是为了防止 IP 被临时封禁,也是爬虫伦理的基本要求:不给目标网站服务器造成压力。

还有一个非常常见的坑:有些网站会校验 Cookie,第一次访问得到的是一个临时的 Cookie,第二次带这个 Cookie 访问才能拿到真实数据。用 requests 的 Session 对象可以自动保存 Cookie。我建议直接用requests.Session()发请求,这样能省掉很多后续排查反爬问题的时间。

2.3 核心爬虫代码实现

下面给出一段完整的爬虫示例代码。它会请求目标天气网站的某城市页面,解析并保存天气数据。注意,代码中的选择器和网站 URL 需要根据你实际选择的目标网站做调整,但整体结构是通用的。

import requests from bs4 import BeautifulSoup import pandas as pd import time import random # 构造请求头,模拟真实浏览器 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://weather.example.com/", "Accept-Language": "zh-CN,zh;q=0.9" } def fetch_weather(city_url): """ 获取指定城市天气页面的 HTML 文本。 city_url: 目标城市天气页面地址 """ session = requests.Session() session.headers.update(headers) resp = session.get(city_url, timeout=10) resp.encoding = resp.apparent_encoding # 自动识别网页编码 if resp.status_code == 200: return resp.text else: print(f"请求失败,状态码: {resp.status_code}") return "" def parse_weather(html): """ 解析 HTML,提取日期、天气、温度等字段。 返回一个字典列表,每个字典代表一天的数据。 """ soup = BeautifulSoup(html, "html.parser") data_list = [] # 假设每条天气记录在 ul.list 下的 li 标签里 items = soup.select("ul.list li") for item in items: date_el = item.select_one(".date") weather_el = item.select_one(".weather") temp_el = item.select_one(".temp") wind_el = item.select_one(".wind") if not (date_el and weather_el and temp_el): continue date = date_el.get_text(strip=True) weather = weather_el.get_text(strip=True) temp_text = temp_el.get_text(strip=True) # 温度字段通常是 "12℃ ~ 23℃" 这类格式,需要拆开 temps = temp_text.replace("℃", "").split("~") if len(temps) == 2: temp_low = float(temps[0].strip()) temp_high = float(temps[1].strip()) else: continue wind = wind_el.get_text(strip=True) if wind_el else "" data_list.append({ "日期": date, "天气": weather, "最低温度": temp_low, "最高温度": temp_high, "风力": wind }) return data_list if __name__ == "__main__": url = "https://weather.example.com/city/101010100" # 替换为目标城市实际地址 html = fetch_weather(url) if html: weather_data = parse_weather(html) df = pd.DataFrame(weather_data) df.to_csv("weather_data.csv", index=False, encoding="utf-8-sig") print(f"成功保存 {len(df)} 条数据") else: print("未获取到网页内容")

这段代码里有一个很容易被忽略但对初学者很关键的细节:resp.encoding = resp.apparent_encoding。如果不设置编码,requests 会使用响应头中声明的编码,但部分网站响应头里的 charset 和实际内容不一致,导致解析出来的中文变成乱码。apparent_encoding 是根据页面内容自动推测出的编码结果,能有效避免这类问题。

解析逻辑中我用的是 CSS 选择器,.select_one(".date")表示选取 class 为 date 的第一个元素。当然也可以用find("div", class_="date"),两者效果一样,看个人习惯。我自己更推荐 CSS 选择器,因为代码更紧凑,而且在面对嵌套不深的 HTML 时可读性更好。

注意保存 CSV 时使用了encoding="utf-8-sig"。如果只用utf-8,生成的 CSV 用 Excel 打开时中文会乱码,因为 Excel 默认用 ANSI 编码解析 CSV;utf-8-sig会在文件开头写入一个 BOM 标记,Excel 就能正确识别。这个细节很多教程都不会提,但每次都能让一批同学的作业“起死回生”。

2.4 数据字段的扩展与采集策略

如果只想让作业达到基本要求,上面的代码已经够用了。但如果想把报告写得更有深度,可以考虑扩充数据字段和采集范围。

一是增加城市维度,比如分别爬取北方城市和南方城市的数据,做对比分析;二是增加时间跨度,爬取多个自然月的数据,分析季节变化趋势;三是增加空气质量指数。这些扩展会让报告的分析维度更丰富,图表数量也会更多。

不过要提醒的是,采集多个城市的数据会显著增加请求数量。假设你要爬 10 个城市各 30 天的数据,即使每个城市只请求 1 次,也需要 10 次请求,加上每次请求间隔 2 到 3 秒,整个过程不到一分钟。但如果页面采用分页展示历史数据,爬取多页时要尤其注意 URL 中的页码参数和日期参数,否则很容易爬到重复数据。

3. 数据清洗:别让脏数据毁掉图表

3.1 读取数据与初步检查

爬虫保存的数据往往不会直接可用。因为页面结构变化或者解析遗漏,可能产生空值、重复值、格式不一致等问题。所以在画图之前,必须先读取 CSV 并做检查。

import pandas as pd df = pd.read_csv("weather_data.csv", encoding="utf-8-sig") print(df.head()) print(df.info()) print(df.describe())

df.head()用来查看前几行数据,确认字段是否完整;df.info()用来查看每列的数据类型和缺失值数量;df.describe()查看数值列的统计指标,比如均值、最值、分位数,这些信息能帮助发现异常值。如果最低温度出现 -999 这样的占位符,或者最高温度明显偏离其他值,那就要注意了。

3.2 常见数据问题与处理方案

天气数据的常见问题大致有四类:日期格式不统一、温度字段混入单位或非数值字符、天气现象描述不一致、缺失值。

日期格式问题:有的网站在不同页面里日期可能显示为2024-01-01、1月1日或2024/1/1。处理思路是统一转换为 pandas 的 datetime 类型:pd.to_datetime(df["日期"], format="mixed", errors="coerce")。转换后方便按月份、季节分组统计。注意errors="coerce"会在转换失败时生成 NaT 而不是抛异常,方便后续过滤。

温度字段问题:有时候爬取下来的字符串里除了数字还带着℃或者空格。处理方式有两种,一种是在解析阶段就直接清理,另一种是在清洗阶段用正则或 pandas 的字符串方法统一处理。我倾向于在解析阶段就处理干净,因为越是靠前修复问题,后面越省事。

缺失值处理:如果缺失的数据很少,可以直接删除:df.dropna()。如果缺失的是温度这类连续型字段,也可以用该列均值填充:df["最低温度"].fillna(df["最低温度"].mean())。但要在报告里如实说明采用了哪种方式,不要默默处理,这体现了对数据质量的意识。

天气现象不一致:比如“晴”和“晴天”、“多云”和“阴”这些描述,只是文字形式不同,本质是同一天气或相近天气。在做天气类型统计分析时,需要人为归并,把相近的描述统一成标准类别。这一步虽然有点繁琐,但它直接决定了后续饼图或柱状图的准确性。

3.3 新增派生字段的思路

为了让可视化素材更丰富,可以在清洗过程中新增一些派生字段。比如从日期中提取“月份”和“星期”,用于分析不同月份的温差变化,或者工作日与周末的气温差异;把“最高温度 - 最低温度”计算为“温差”,用于分析昼夜温差。

df["日期"] = pd.to_datetime(df["日期"]) df["月份"] = df["日期"].dt.month df["星期"] = df["日期"].dt.dayofweek # 0 表示周一 df["温差"] = df["最高温度"] - df["最低温度"]

别小看这些从现有数据中组合出来的字段。在报告里,一句“我们进一步计算了昼夜温差,发现该城市春季温差最大,平均达到 12℃”就能体现你在思考数据背后的规律,而不是完成一次机械的搬运。

4. 可视化:让天气数据开口说话

4.1 中文字体问题是第一个拦路虎

matplotlib 默认字体不包含中文字符,直接绘制中文标签会出现一个个方框,也就是传说中的“豆腐块”。这个问题在项目开始时就要解决。

import matplotlib import matplotlib.pyplot as plt # 设置支持中文的字体 plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "PingFang SC"] plt.rcParams["axes.unicode_minus"] = False # 解决负号显示异常

字体列表里放了你系统上可能存在的字体名,matplotlib 会逐个尝试。Windows 一般可以写SimHei或Microsoft YaHei,macOS 写PingFang SC或Arial Unicode MS。axes.unicode_minus设为 False 是为了防止坐标轴上的负号显示成方框。

如果是 Linux 服务器上跑代码,系统可能一个中文字体都没有,需要手动安装字体文件并刷新 matplotlib 的字体缓存,这个复杂度建议不要在报告中大篇幅展开,直接说明“本地运行请使用本机支持的中文字体”即可。

4.2 理解图表在报告中的叙事作用

可视化不是把数据画出来就完了,每张图都要能回答一个具体的问题。比如:这一年的气温走势如何,最低温出现在哪一天,最高温出现在哪一天,降水集中在哪几个月,不同天气类型出现的频率如何?带着问题去选图,报告才能逻辑连贯。

我建议一个完整项目至少配备四张图:

  1. 最高温和最低温的折线走势图,展示温度的时间变化规律。
  2. 降水量的柱状图,展示降水的时间分布。
  3. 天气类型的饼图或柱状图,展示不同天气现象出现的频次。
  4. 温度分布的箱线图,展示最高温、最低温的分布形态和异常值。

4.3 折线图与柱状图实现

折线图是最直观的温度走势图。如果数据跨多个月,直接把每天两个温度画出来,图会非常密集。一种做法是只画最高温曲线,另一种做法是先用groupby("月份")分组计算月均值,再画折线。月更符合人类对“季节变化”的感知。

monthly = df.groupby("月份").agg({"最高温度": "mean", "最低温度": "mean"}).reset_index() plt.figure(figsize=(10, 6)) plt.plot(monthly["月份"], monthly["最高温度"], marker="o", label="月平均最高温") plt.plot(monthly["月份"], monthly["最低温度"], marker="s", label="月平均最低温") plt.xlabel("月份") plt.ylabel("温度 / ℃") plt.title("某城市各月平均气温变化") plt.legend() plt.grid(True, linestyle="--", alpha=0.5) plt.savefig("temperature_trend.png", dpi=300, bbox_inches="tight") plt.show()

柱状图用于降水量这类“总量”型的字段展示。如果只有天气现象字段而没有降水量数值,可以把“雨”“雪”“大雨”“小雨”归并为“降水事件”,用事件频次替代降水量,同样能反映降水规律。这种替代思路在数据缺失时非常实用。

4.4 饼图与箱线图的组合使用

天气类型频次用饼图展示最形象,但饼图的分类不能太多,否则图例密密麻麻。我在实际项目中会把“晴”“多云”“阴”等高频类别单独保留,低频类别合并为“其他”。这样既保留了主要信息,又避免了视觉杂乱。

箱线图则更适合表现温度分布。它把每一天的最高温看成一个观测值,通过箱体的位置和长度能直观判断气温的中位数、四分位距和异常值。比如“该城市五月的最高温中位数是 28.5℃,但出现了一次 35℃ 的异常高温”这样的结论,就是箱线图给出来的。

fig, axes = plt.subplots(1, 2, figsize=(12, 5)) temp_data = [df[df["月份"] == m]["最高温度"].values for m in range(1, 13)] axes[0].boxplot(temp_data, labels=range(1, 13)) axes[0].set_title("各月最高温分布箱线图") axes[0].set_xlabel("月份") axes[0].set_ylabel("最高温度 / ℃") weather_counts = df["天气"].value_counts() axes[1].pie(weather_counts.values[:5], labels=weather_counts.index[:5], autopct="%.1f%%", startangle=90, counterclock=False) axes[1].set_title("主要天气类型占比") plt.tight_layout() plt.savefig("weather_analysis.png", dpi=300, bbox_inches="tight") plt.show()

这一张图同时输出两个子图,既能节省报告版面,也显得观察角度更全面。箱线图会显示可能存在的异常值点,报告里可以专门分析这些异常日期,说明当时出现了什么天气过程。如果数据里恰巧包含寒潮或高温事件,这部分的解读会非常有亮点。

4.5 图表保存与报告插入要点

画完图之后,推荐统一用plt.savefig(..., dpi=300, bbox_inches="tight")保存,300dpi 打印到纸上或嵌入 Word 文档都足够清晰。bbox_inches="tight"会自动裁剪空白边缘,避免图表周围有大面积白边。在报告里插入图片时,先写结论再放图,比如“3 月降水事件出现次数最多,是全年最多雨的月份”,然后紧跟柱状图,这样老师读起来不会被图片带着跑,而是顺着你的分析思路走。

5. 大作业报告的结构设计与写作思路

5.1 报告标准骨架

课程设计报告的评阅人通常没有时间逐行看代码,他拿到报告看的是结构、逻辑和结果呈现。一个能拿高分的报告建议按下面的结构组织:

  1. 项目背景与目标:说明为什么选择天气数据,目标是什么。
  2. 需求分析:从用户角度列出项目需要实现的功能模块。
  3. 技术方案与工具:介绍使用 Python、requests、BeautifulSoup、pandas、matplotlib 的理由。
  4. 系统设计:画模块划分和整体流程,描述爬虫模块、数据处理模块、可视化模块的分工。
  5. 详细实现:按模块粘贴核心代码,每段代码前用三五行文字说明“这段代码的功能和关键点”。
  6. 结果分析与展示:插入所有图表,逐图说明结论。
  7. 项目总结与展望:总结完成了什么,还有哪些可以改进的地方。
  8. 参考文献:列出官方文档、学习资料等。

5.2 摘要与关键词的写法

摘要不是把目录抄一遍,而是用 200 到 300 字概括整个项目做了什么、怎么做的、得出什么结论。比如:“本项目以某城市天气预报为数据源,利用 Python 爬虫技术采集连续三个月的天气数据,使用 pandas 完成数据清洗,并通过 matplotlib 从温度变化、降水分布、天气类型等维度进行可视化分析。分析结果表明……”这种写法的好处是让评阅人第一眼就抓住项目的核心工作量。

关键词推荐填:Python、网络爬虫、天气数据、数据清洗、数据可视化。这几个词也是题目里出现过的核心词,保持统一能增加报告的辨识度。

5.3 报告中怎样展示代码

很多同学喜欢把全部代码塞进报告,几十页全是代码,这反而会拉低质量。正确的做法是精选具有代表性的代码片段,每段 10 到 20 行为宜,并在代码上方写清楚“要解决什么问题”,代码下方标注“关键点在哪里”。比如爬虫模块,展示请求头发送和解析逻辑就够了,不需要把每个函数都贴一遍。文档整体代码占比控制在 30% 到 40% 比较合适,其余是思路说明和结果分析。

5.4 答辩时老师常问的问题

答辩环节往往比报告本身更考验人。老师常见的问题包括:为什么选这个网站,数据会遇到什么反爬机制?如果网站改版了,你的爬虫还能用吗?CSV 里数据缺失怎么办?你的图展示了什么结论?你如何证明爬取的数据是准确的?

准备思路也很简单,每个问题都对应项目中的一个真实环节。比如反爬问题答“我通过设置浏览器 User-Agent 和延时访问降低请求频率”,验证数据准确问题答“我抽样检查了 10 天的数据,与网页页面人工核对一致”。只要项目是自己一步步写出来的,这些问题都能接得住。

6. 常见问题与排错技巧实录

6.1 请求返回 403 或空内容

403 是访问被拒的典型标志,绝大多数情况是请求头缺失或不合规。排查步骤:先把浏览器上的 User-Agent 完整复制到代码里,再确认网站是否有基础登录要求。如果返回空内容但状态码是 200,大概率是页面编码问题或数据是异步加载的。前者按resp.encoding = resp.apparent_encoding处理;后者则需要切换到接口请求方式。

6.2 解析结果为空列表

这是初学者最容易挫败的环节。写完选择器,运行半天,结果items是空的。第一步,不要在代码里猜,直接把抓到的 HTML 保存成文本文件,用编辑器打开,搜索 “晴” 或 “日期” 等关键词,确认数据是否真的在 HTML 里。第二步,确认你写选择器时用的是正确的 class 名称,有些网站的 class 是动态生成的,每次刷新都可能变化,这时候就需要改用更多的结构关系来找元素,比如先找到包含整块列表的父节点,再逐层往下获取。

6.3 CSV 文件用 Excel 打开乱码

保存 CSV 时用encoding="utf-8-sig"就能解决。如果已经保存成utf-8了,也可以手动用 Excel 的“数据—自文本”方式导入,并指定编码为 UTF-8,但这样做很麻烦,不如直接改代码重新跑一遍。

6.4 图表中文字体显示为方框

这属于本机字体问题。先用 Python 查看 matplotlib 当前可用的字体列表:

from matplotlib import font_manager fonts = [f.name for f in font_manager.fontManager.ttflist] print(fonts)

看你的系统字体里哪一个包含中文字符,然后手动指定。如果你的系统只有英文版,建议先安装一个中文字体文件再设置。一个简单的替代方案是给所有图表改用英文标签,但在课程报告中,中文标签是刚需,所以还是把字体问题彻底解决比较好。

6.5 请求次数过多导致临时封禁

如果短时间内连续请求几十次,有些网站会暂时屏蔽 IP。遇到这种情况,停止爬取几分钟后一般会恢复。日常处理时,把请求间隔拉长到 3 到 5 秒,并增加一次随机延迟,就能大幅降低触发封禁的概率。核心逻辑是:我们做的是课程项目,数据量不大,没必要也不应该高频请求。

7. 经验总结与扩展方向

从我这个项目的实操体验来说,最大的收获不是学会了某个库的某个函数,而是建立了“拿到一个问题先拆解流程”的思维习惯。爬虫、清洗、可视化三个模块看起来很独立,但实际调试时它们是互相纠缠的:前端解析错了,后面所有图表就跟着错;CSV 编码没处理好,报告里贴出来的表格就是乱码。每一步都稳扎稳打,整体才能顺利跑通。

如果你交完作业还想继续精进,这个项目有很多自然的扩展点。你可以把抓取目标从单一城市扩展到多个城市,做区域气候对比;也可以在爬虫层引入代理池和 Web 框架,做成一个小型天气查询 API;还可以在可视化层引入 pyecharts 生成交互式图表,放到 Web 页面里展示。这些方向本质上都是在同一个骨架上添砖加瓦,前期基础打得越扎实,后面扩展越轻松。

最后分享一个小技巧:无论代码多忙,爬下来的原始数据一定要保留一份,不要覆盖。我在做可视化调整时,就曾因为反复运行爬虫把原始 CSV 覆盖掉了,导致数据字段格式变乱,排查了半天才发现是源头文件的问题。把原始数据、清洗后数据、图表输出和报告草稿分目录存放,看起来是小事,但能在最后交作业前帮你省下大量时间。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询