20244303 2025-2026-2 《Python程序设计》实验四报告

20244303 2025-2026-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 2443
姓名: 谢昕彤
学号:20244303
实验教师:王志强
实验日期:2026年5月28日
必修/选修: 公选课
一、实验分析
1.实验目的
运用Python网络爬虫技术,自动爬取网页天气数据,实现数据自动化获取;并对爬取的温度、湿度、天气状况进行解析、存储与统计分析;利用数据可视化技术绘制图表,直观展示气象变化趋势;实现每日定时自动向微信推送天气提醒,完成自动化提醒工具。
2.预期功能
本次实验预期实现一套轻量化、全自动的天气数据采集、分析与推送系统,具体功能如下:
(1)爬虫功能:自动请求网页,爬取当日及未来天气数据;
(2)数据解析与保存:提取有效信息并保存为CSV文件;
(3)数据统计:计算最高温、最低温、平均湿度;
(4)可视化图表:绘制温湿度变化曲线;
(5)天气报告:自动生成天气文案;
(6)微信推送:将报告发送到个人微信;
(7)自动化运行:可定时自动爬取+自动推送。
3.预期结果
爬虫能成功获取完整天气数据;程序可稳定自动推送;微信客户端能够正常接收天气提醒消息;可视化图表清晰美观、数据准确。
二、实验设计
整体架构:实验采用模块化分层设计,按照 “数据采集 — 数据处理 — 数据分析 — 消息输出 — 自动化控制” 流程,将总体分为五个模块。
1.爬虫模块(数据采集层)
作为系统数据源核心,通过requests模拟浏览器访问天气网页,利用BeautifulSoup解析网页HTML结构,精准抓取当日逐时天气、未来14天天气、温度、湿度、风向、风级等原始数据,进行数据采集。
2.数据处理模块(数据处理层)
利用pandas对爬虫获取的网页原始数据进行处理,去重、过滤无效字符、结构化整理,统一数据格式,并将整理后的标准数据保存为CSV文件,方便后续读取、统计与分析。
3.数据可视化模块(数据分析层)
读取保存处理好的天气数据,利用matplotlib绘制24小时温湿度变化趋势图、14天温度对比图,并标注极值数据,实现数据可视化展示,直观呈现天气变化规律。
4.微信推送模块(功能输出层)
采用第三方BotTalk微信推送接口,生成当天天气预报文案,并根据分析结果提供智能出行建议,通过网络请求推送至个人微信,实现微信消息提醒。使用tkinter实现发送操作界面,提升人机交互体验。
5.定时任务模块(自动化控制层)
利用threading.Timer 多线程定时器实现系统自动化调度,使程序运行情况下,可自动爬取数据、自动分析、自动生成报告、自动推送,同时也支持随时手动触发推送,实现全自动、半自动并行模式。
三、实验过程实现
本次实验按照设计的模块化思路,分步完成代码编写、功能调试、问题修复,实现天气爬取、数据处理、可视化展示、微信自动推送功能,具体实现过程如下:
1.天气爬虫功能实现
(1)首先搭建网页请求基础函数,通过配置浏览器请求头模拟正常用户访问,规避网站访问拦截,设置超时参数防止程序卡死,统一网页编码为UTF-8,解决中文乱码问

点击查看代码
#获取网页
def gethtml(url):
    headers = {"User-Agent": "Mozilla/5.0"}
    r = requests.get(url, headers=headers, timeout=30)
    r.encoding = "utf-8"
    return r.text
(2)针对中国天气网数据特性,静态天气数据通过BeautifulSoup解析HTML标签获取,24小时逐小时动态天气数据隐藏在页面Script脚本中,通过字符串截取剥离无效字符后,利用JSON解析提取结构化数据。
点击查看代码
#24小时数据
def day24data(html):
    now = datetime.now()
    nowh = now.hour

    daylist = []
    bs = BeautifulSoup(html, "html.parser")
    data2 = bs.find_all('div', class_='left-div')
    text = data2[2].find('script').string
    text = text[text.index('=') + 1 : -2]
    jd = json.loads(text)
    daydata = jd['od']['od2']
(3)为适配真实时间逻辑,自定义时序排序规则,以系统当前小时为节点,将未来时段数据前置、过往时段数据后置,实现24小时顺延展示。实验过程中发现网站原始数据存在小时重复数据问题,通过创建集合存储已遍历小时编号,自动过滤重复记录,保证最终只保留24条唯一、有序的小时数据。
点击查看代码
def sortrule(item):
    h = int(item['od21'])
    return (0 if h >= nowh else 1, h)

datasort = sorted(daydata, key=sortrule)

#改进:每个小时只保留一条,解决weather1第一个小时重复问题
seen_hour = set()
for i in datasort:
    h = i['od21']
    if h not in seen_hour:
        seen_hour.add(h)
        daylist.append([
            i['od21'], i['od22'], i['od24'], i['od25'],
            i['od26'], i['od27']
        ])
    if len(daylist) >= 24:
        break
(4)最后分别爬取前7天、后7天预报数据,拼接整合为完整14天数据集,统一日期、温度、风向格式,批量保存为weather1.csv、weather14.csv标准文件,完成数据持久化存储。
点击查看代码
#保存文件
def savecsv(name, head, data):
    with open(name, "w", newline="", encoding="utf-8-sig") as f:
        w = csv.writer(f)
        w.writerow(head)
        w.writerows(data)
2.数据清洗与预处理实现 实验开始时使用fillna填充空值,但运行程序时出现版本报错,排查发现新版pandas2.0以上已废弃fillna(method='ffill')语法。后替换为ffill()前向填充方法,适配新版本库,保证空缺数据平滑填充和时序数据连续性。
点击查看代码
temp = data['温度'].ffill()
hum = data['湿度'].ffill()
……
low = data['最低气温'].ffill()
high = data['最高气温'].ffill()
同时对温度、风向异常数据做兼容处理,针对无高低温区分、风向转义、空风级等异常情况设置默认值,避免程序解析报错,保证数据完整性与规范性。 3.数据可视化功能实现 导入matplotlib(用于绘图)、numpy(用于雷达图计算)库完成可视化开发。 (1)首先配置全局中文字体,设置黑体、微软雅黑双字体兼容,关闭负号乱码渲染,解决图表中文显示为方框的问题。
点击查看代码
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
(2)读取本地CSV结构化数据,分别绘制24小时温度变化曲线、24小时湿度变化曲线、14天高低温对比曲线图、14天风向分布雷达图。 * 24小时温度、湿度变化曲线
点击查看代码
#24小时温度+湿度图
def day_plot(data):
    hour = data['小时']
    temp = data['温度'].ffill()
    hum = data['湿度'].ffill()

    #温度图
    plt.figure(figsize=(12,6))
    x = range(24)
    plt.plot(x, temp, 'r-o', label='温度')
    for i,v in enumerate(temp):
        plt.text(i, v+0.3, f'{v}', ha='center')
    plt.plot([0,24], [temp.mean()]*2, 'b--', label='平均温度')
    plt.xticks(x, hour)
    plt.legend()
    plt.title('24小时温度')
    plt.xlabel('时间')
    plt.ylabel('℃')
    plt.show()

    #湿度图
    plt.figure(figsize=(12,6))
    plt.plot(x, hum, 'b-o', label='湿度')
    for i,v in enumerate(hum):
        plt.text(i, v+1, f'{v}', ha='center')
    plt.plot([0,24], [hum.mean()]*2, 'r--', label='平均湿度')
    plt.xticks(x, hour)
    plt.legend()
    plt.title('24小时湿度')
    plt.xlabel('时间')
    plt.ylabel('%')
    plt.show()
图表显示数据:绘制折线+标记点;显示每个小时数值;绘制平均值虚线;自动标注坐标轴

ScreenShot_2026-05-29_214454_692
ScreenShot_2026-05-29_214510_172

  • 14天高低温对比曲线图
点击查看代码
#14天高低温曲线
def shisi_tian(data):
    date = data['日期']
    low = data['最低气温'].ffill()
    high = data['最高气温'].ffill()

    x = range(14)
    plt.figure(figsize=(14,6))
    plt.plot(x, high, 'r-o', label='最高温')
    plt.plot(x, low, 'b-o', label='最低温')

    for i,v in enumerate(high): plt.text(i, v+0.5, f'{v}', ha='center')
    for i,v in enumerate(low): plt.text(i, v-0.8, f'{v}', ha='center')

    plt.plot([0,14], [high.mean()]*2, 'k--', label='平均最高温')
    plt.plot([0,14], [low.mean()]*2, 'c--', label='平均最低温')
    plt.xticks(x, date, rotation=45)
    plt.legend()
    plt.title('14天温度')
    plt.xlabel('日期')
    plt.ylabel('℃')
    plt.show()
图表显示数据:同时画最高温(红)、最低温(蓝);标记每日温度数值;显示平均高低温虚线;日期旋转 45 度,防止重叠

ScreenShot_2026-05-29_214632_108

  • 14天风向分布雷达图
点击查看代码
#风向雷达图
def fengxian(data):
    counts = {'北风':0,'南风':0,'西风':0,'东风':0,'东北风':0,'西北风':0,'西南风':0,'东南风':0}
    for w in data['风向']:
        if '转' in w:
            a,b = w.split('转')
            if a in counts: counts[a]+=1
            if b in counts: counts[b]+=1
        elif w in counts: counts[w]+=1

    labels = list(counts.keys())
    vals = list(counts.values())

    fig, ax = plt.subplots(figsize=(6,6), subplot_kw={'projection':'polar'})
    angles = np.linspace(0, 2*np.pi, len(labels), endpoint=False)
    vals = vals + [vals[0]]
    angles = np.concatenate([angles, [angles[0]]])

    ax.plot(angles, vals, 'o-')
    ax.fill(angles, vals, alpha=0.25)
    ax.set_thetagrids(angles[:-1]*180/np.pi, labels)
    plt.title('风向统计')
    plt.show()

图表显示数据:统计 8 个风向出现次数;处理 “风向转”(东风转南风 = 各记一次);极坐标雷达图可视化风向频率

ScreenShot_2026-05-29_214642_364

4.微信推送与GUI界面实现
(1)基于tkinter搭建轻量化桌面交互界面。程序启动后自动读取本地天气数据,解析当日天气、温度区间、当前气温、风向风力等信息,按照模版生成简易的天气播报文案。

点击查看代码
#生成天气内容
def create_msg():
    day_data = pd.read_csv("weather1.csv")
    all_data = pd.read_csv("weather14.csv")
    today = all_data.iloc[0]

    content = (
        f"日期:{today['日期']}\n"
        f"天气:{today['天气']}\n"
        f"温度:{today['最低气温']}℃~{today['最高气温']}℃\n"
        f"当前温度:{day_data.iloc[0]['温度']}℃\n"
        f"风向:{today['风向']} {today['风级']}"
    )
    return "天气提醒", content

#界面
if __name__ == "__main__":
    root = tk.Tk()
    root.title("天气推送")
    root.geometry("500x350")
    root.protocol("WM_DELETE_WINDOW", close)

    tk.Label(root, text="天气微信推送", font=("微软雅黑", 16)).pack(pady=10)
    tk.Label(root, text=f"每日 {send_hour}:{send_min:02d} 自动发送", fg="blue").pack()

    tk.Button(root, text="立即发送", command=lambda: Thread(target=push, daemon=True).start(),
              bg="green", fg="white").pack(pady=15)

    tk.Label(root, text="日志:").pack()
    log_box = scrolledtext.ScrolledText(root, width=60, height=10)
    log_box.pack()

(2)实验前期单线程推送存在界面卡顿、日志卡死问题,通过引入多线程技术,将推送任务放入后台线程执行,主线程专注界面渲染,彻底解决程序阻塞问题。

点击查看代码
tk.Button(root, text="立即发送", command=lambda: Thread(target=push, daemon=True).start(),
          bg="green", fg="white").pack(pady=15)

(3)利用Timer定时器编写循环定时任务,增加时间判断逻辑,若程序启动时已过当日推送时间,自动顺延至次日执行,本实验设置可以实现7×24小时循环自动推送。

点击查看代码
#设置定时
def set_timer():
    global timer
    if not run:
        return
    now = datetime.now()
    target = now.replace(hour=send_hour, minute=send_min, second=0)
    if now > target:
        target += timedelta(days=1)
    sec = (target - now).total_seconds()
    timer = Timer(sec, lambda: (push(), set_timer()))
    timer.start()

(4)同时对接BotTalk第三方接口,无需认证等程序,获得对应Senkey并在代码中写入,实现个人微信稳定私聊推送。

点击查看代码
#配置
key = "284f6ddff397364420d1118c93dc44ff"
send_hour = 20
send_min = 45

#微信推送
def send_wx(title, content):
    url = f"https://bot-talk.com/{key}.send"
    requests.post(url, json={"title": title, "desp": content})

四、实验结果与问题分析
1.实验最终结果
本次实验实现了全部预期功能:
(1)爬虫功能正常稳定,可自动抓取24小时逐小时、14天完整天气数据,通过去重、清洗处理后,数据无重复、无缺失、时序正确,并生成标准化CSV数据文件;
(2)数据可视化效果良好,四类天气图表绘制完整,中文显示正常、数据标注清晰、趋势直观,可精准反映温湿度变化规律与风向分布特征;
(3)GUI交互界面运行流畅,可实现手动即时推送与每日定时自动推送双模式。
代码上传git
weather
analysis
weixin
代码运行视频

2.实验遇到的问题及完整解决方案
问题1:天气小时数据重复
问题描述:中国天气网原始接口返回数据存在冗余,同一小时出现多条重复记录,导致导出CSV数据重复、时序错乱,影响数据分析与图表展示。
解决方案:新增集合去重机制,遍历排序后的时序数据,记录已保存的小时编号,自动过滤重复数据,避免数据重复显示问题。
问题2:新版pandas语法报错
问题描述:高版本pandas废弃fillna(method='ffill')写法,程序运行直接报错,无法完成空值填充,导致图表绘制失败。
解决方案:替换为pandas新版专属ffill()方法,语法简洁且完全兼容原填充逻辑,适配新版本运行环境,成功解决版本兼容报错问题。
问题3:Matplotlib图表中文乱码
问题描述:默认绘图字体不支持中文,图表标题、坐标轴、图例中文全部显示为方框,无法正常查看图表信息。
解决方案:全局配置微软雅黑、黑体双中文字体,关闭unicode负号特殊渲染,解决中文乱码、负号显示异常问题。
问题4:推送任务导致GUI界面卡顿
问题描述:单线程模式下,推送任务执行时独占主线程,导致界面卡顿、按钮无法点击,用户体验差。
解决方案:引入多线程机制,将消息推送任务放置后台子线程运行,主线程仅负责界面渲染与交互,彻底解决界面阻塞卡顿问题。
问题5:定时任务跨天失效
问题描述:若程序启动时间晚于当日设定推送时间,定时器无法显示设置成功。
解决方案:增加时间判断逻辑,对比当前时间与目标推送时间,超时则自动顺延24小时,实现循环定时推送,保证该功能运行。
五、实验总结与课程体会
1.实验总结
本次Python综合实验完成了天气数据采集、数据处理、可视化分析、微信自动化推送的全流程开发,实现了一套智能天气提醒系统。项目采用模块化分层设计,各模块分工明确,解决了许多兼容性、数据异常、程序Bug问题。
实验过程中,我熟练掌握了网络爬虫网页解析、动态JSON数据提取、结构化数据清洗、可视化图表绘制、GUI界面开发、多线程定时任务、第三方接口调用等核心技术,突破了单一语法练习的局限,提高了Python项目的开发、调试、优化能力。
2.课程学习体会
本学期我有幸选修了王志强老师的《Python程序设计》公选课,这是一段非常珍贵且充实的学习经历。在选修本课程之前,我仅接触过简单的C语言基础,几乎没有Python编程经验,属于零基础入门的学生。最初我对代码编写、程序逻辑、库函数调用都比较陌生,面对编程学习内心也存在一定畏难情绪,担心无法跟上课程节奏。但一学期学习下来,在王老师耐心、细致、风趣的教学引导下,我不仅顺利完成了全部课程学习,还独立完成了本次综合实践项目,收获远超预期。
王老师教学经验丰富、讲课节奏清晰舒缓,十分照顾零基础同学的学习节奏。课堂上,老师不会生硬堆砌理论知识,而是常常结合生活实例类比抽象的编程逻辑,用通俗易懂的语言拆解复杂知识点,让原本晦涩的语法规则、程序结构、逻辑思维变得简单易懂。课程内容安排科学合理、循序渐进,既覆盖了Python基础语法、流程控制、函数封装、文件操作等核心知识点,又通过实操练习帮助我们巩固所学,让我这样基础薄弱的初学者可以稳步积累、逐步提升。
本次综合天气项目实践,是对整学期课程知识的全面复盘与落地。从最初只会抄写简单代码,到逐步理解爬虫采集、数据清洗、可视化绘图、接口推送、自动化定时任务的完整逻辑,再到独立排查报错、优化程序,我真正跳出了单纯的“背语法、敲代码”的学习模式。在不断调试、不断解决问题的过程中,我慢慢建立起编程思维,学会了先拆分问题、再分步实现的解决思路,摆脱了面对代码无从下手的困境。
这门课程带给我的不仅是Python编程技能,更重要的是思维方式的转变。我深刻认识到,编程不是机械的代码堆砌,而是解决实际问题的工具与思路。同时,我也克服了对编程的恐惧心理,建立了学习自信,养成了动手实践、不惧报错、主动排查问题的学习习惯。这些能力与思维的提升,不仅适用于Python学习,对我今后所有课程的学习、问题处理都有着极大的帮助。
由衷感谢王老师一学期的辛勤付出与耐心教导,课堂氛围轻松愉悦、知识点讲解细致透彻,让这门公选课成为我大学期间收获最大、最值得推荐的课程之一。即使课程结束,我在课堂上学到的编程知识、逻辑思维和实操能力,也会在今后的学习生活中持续发挥作用,我也会在课余时间继续深入学习Python相关应用。
3.课程意见与建议
结合自身零基础、基础薄弱的学习体验,以及本学期整体课程学习情况,我对本课程提出几点真诚、贴合实际的改进建议,希望能够让课程教学更加完善,帮助更多零基础同学高效学习:
(1)课堂上可以适当拓展Python的多元化应用场景,比如简单讲讲Python在数据分析、自动化办公、人工智能等领域的应用,这样可以让同学们看到所学知识的实际价值,也能激发学习兴趣。
(2)对于我们初学者而言,大部分学习障碍都来源于代码报错、库版本不兼容、环境配置异常等问题。建议老师增加常见报错案例讲解(常见或者不常见的),解决报错的排查思路与解决方法,调试技巧,帮助基础薄弱的同学提升实操排错能力,降低项目实践难度。
(3)鼓励同学之间交流学习经验,有些问题可能老师讲完我们一时没完全理解,但如果能有一个小组讨论或者线上交流平台,大家可以互相帮助,学习效率也会更高。
总体而言,这是一门极具价值、体验感极佳的通识课程。课程难度适中、内容实用、老师教学方式幽默风趣,非常适合零基础同学入门学习。
再次感谢王老师一学期的悉心教导和课代表的课后答疑帮助,让我收获知识、提升能力、开阔思维,受益匪浅。我也会积极向学弟学妹推荐这门优质课程,让更多同学感受编程的魅力、收获成长。

posted @ 2026-05-30 14:38  ZnCu_  阅读(76)  评论(0)    收藏  举报