20241204 2025-2026-2 《Python程序设计》实验4报告

20241204 2025-2026-2 《Python程序设计》实验4报告

课程:《Python程序设计》
班级: 2412
姓名: 李浩铭
学号:20241204
实验教师:王志强
实验日期:2026年5月25日
必修/选修: 公选课

1.实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
例如:利用公开数据集,开展图像分类、恶意软件检测等
例如:利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
例如:爬取天气数据,实现自动化微信提醒
例如:利用爬虫,实现自动化下载网站视频、文件等。
例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等
注:在Windows/Linux系统上使用VIM、PDB、IDLE、Pycharm等工具编程实现。

2.实验过程及结果

2.1实验分析(设计原因)
每天不用特意去查看天气情况,利用此工具即可在每天早上6:30获得想知道城市的天气情况,并设置有温度,湿度,穿搭参考,以及七日天气预报等功能,丰富多样,十分便捷,便利了出行
2.2实验概述
本实验基于 Python 开发自动化微信定时天气推送工具,核心目标是实现每日固定时间自动获取指定城市的实时 / 七日气象数据,自动打开微信、定位好友并发送完整的天气播报消息。程序集成了网络请求、定时任务、系统操作、剪贴板控制、键盘模拟等功能,适用于日常自动化问候、天气提醒等场景。
2.3实验设计
1.整体架构设计
程序采用模块化设计,分为 4 大核心模块
配置模块:用户自定义城市、微信好友、推送时间
数据获取模块:调用第三方 API 获取城市坐标 + 气象数据
数据处理模块:天气代码翻译、温度解析、穿搭建议、预警生成
自动化执行模块:定时触发 + 微信自动发送消息
2.流程设计
启动程序 → 加载用户配置 → 初始化定时任务 → 首次测试推送→ 监听定时任务 → 到达指定时间→ 获取天气数据 → 格式化消息 → 模拟操作微信发送消息
3.核心功能设计
天气获取:调用 Open-Meteo 免费 API,先通过城市名获取经纬度,再根据经纬度获取精准气象数据(温度、湿度、风力、七日预报)。(一开始本来想爬取中国天气网的数据,但AI提示这样爬取可能违反该网站的协议,故此换成这个)
数据可视化处理:将 API 返回的数字天气代码转换为带表情的中文描述,根据温度生成穿搭建议、天气预警,提升消息可读性。
定时任务:使用schedule库实现每日固定时间触发推送任务。
微信自动化发送:通过系统命令启动微信,模拟键盘操作实现搜索好友、粘贴消息、发送消息。
2.4 实验实现过程
步骤一:安装所需第三方库
be5df3dc602234fd24864c6f015b04ca
步骤二:配置地区以及发送人物和定时时间
image
步骤 3:工具函数实现
季节判断:根据当前月份判断春夏秋冬;
穿搭建议:根据实时温度分级生成穿搭推荐;
天气代码映射:将 API 数字编码转为带表情的中文天气。
步骤 4:天气数据获取函数(get_weather)
请求地理编码 API,解析城市经纬度;
请求气象 API,获取实时数据和七日预报数据;
数据清洗:四舍五入温度、计算风力等级、拼接日期星期;
消息格式化:生成包含天气、湿度、风力、穿搭、预警、七日预报的完整播报文本;
异常捕获:处理网络错误、API 无返回数据等问题。
步骤 5:微信自动发送函数(send_wechat)
将天气消息复制到剪贴板;
调用系统命令start weixin://打开微信;
粘贴消息并回车发送,全程添加延时保证操作稳定性。
步骤 6:定时任务与主程序
绑定每日固定时间执行天气推送任务;
程序启动后 5 秒执行一次测试推送;
无限循环监听定时任务,保证程序持续运行。
2.5实验结果
1.pycharm端结果
image
2.微信端结果
程序自动打开微信,自动搜索指定好友,自动粘贴并发送完整的天气播报消息,无人工干预即可完成全流程。
image
3.异常处理结果
网络断开:程序捕获异常,输出气象数据获取异常;
image
通过网络重连成功解决问题
2.6实验优点,缺点
优点:本程序通过对天气内容的抓取,成功实现了气温,体感温度,空气湿度,风力状况,穿搭参考,以及未来七日提醒等多种功能,(符合实验要求:至少五个功能)充分体现程序功能多样性
缺点:运行本代码时需要将电脑与微信同时登录,并非仅打开程序即可,在一定程度上比较复杂

3.实验源代码

import requests
import schedule
import time
import subprocess
import pyperclip
import keyboard
from datetime import datetime, timedelta

CITY = "北京"
WX_NAME = "清风浦"
SEND_HOUR = 6
SEND_MINUTE = 30

weather_map = {
0: "☀️ 晴", 1: "🌤 大部晴", 2: "⛅ 多云", 3: "☁️ 阴天",
45: "🌫️ 雾", 48: "🌫️ 雾凇", 51: "🌦️ 小毛毛雨", 53: "🌦️ 毛毛雨", 55: "🌧️ 大毛毛雨",
61: "🌧️ 小雨", 63: "🌧️ 中雨", 65: "🌧️ 大雨", 71: "❄️ 小雪",
73: "❄️ 中雪", 75: "❄️ 大雪", 80: "🌦️ 小阵雨", 81: "🌦️ 中阵雨",
82: "🌧️ 大阵雨", 95: "⛈️ 雷阵雨"
}

wind_level = [
"无风", "软风", "轻风", "微风", "和风", "清风", "强风",
"疾风", "大风", "烈风", "狂风", "暴风", "台风"
]

def get_season():
m = datetime.now().month
if m in [3, 4, 5]:
return "春季"
if m in [6, 7, 8]:
return "夏季"
if m in [9, 10, 11]:
return "秋季"
return "冬季"

def get_cloth(temp):
if temp < 0:
return "🥶 极寒:羽绒服、厚棉装"
if temp < 10:
return "🧥 寒冷:厚外套搭配毛衣"
if temp < 20:
return "👕 凉爽:轻便薄外套即可"
if temp < 28:
return "👕 舒适:常规长短袖穿搭"
return "🩳 炎热:清凉短袖短裤穿搭"

def get_weather(city, is_morning=True):
try:
geo_url = f"https://geocoding-api.open-meteo.com/v1/search?name={city}&language=zh"
geo_res = requests.get(geo_url, timeout=15).json()

if "results" not in geo_res or len(geo_res["results"]) == 0:
return "❌ 无法获取城市坐标,请检查城市名"

lat = geo_res["results"][0]["latitude"]
lon = geo_res["results"][0]["longitude"]
city_name = geo_res["results"][0]["name"]

weather_url = (
f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}"
"&current=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m"
"&daily=weather_code,temperature_2m_max,temperature_2m_min"
"&timezone=auto"
)
weather_res = requests.get(weather_url, timeout=15).json()
current = weather_res["current"]
daily = weather_res["daily"]

temp = round(current["temperature_2m"])
feel_temp = round(current["apparent_temperature"])
weather_text = weather_map.get(current["weather_code"], "🌫️ 未知天气")
wind_idx = min(round(current["wind_speed_10m"] // 3), 12)
wind_desc = wind_level[wind_idx]

now = datetime.now()
week_list = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
week = week_list[now.weekday()]
date_str = now.strftime("%Y-%m-%d")

msg_head = "☀️ 早安天气播报"
msg = f"""
{msg_head}
🏙️ 播报城市:{city_name}
🍃 所属季节:{get_season()}
📆 播报日期:{date_str} {week}
━━━━━━━━━━━━━━━━━━━━
{weather_text}
🌡 实时气温:{temp}℃
😶 体感温度:{feel_temp}℃
💧 空气湿度:{current['relative_humidity_2m']}%
💨 风力状况:{wind_desc} 风速{current['wind_speed_10m']}km/h
📊 今日气温区间:{round(daily['temperature_2m_min'][0])}℃ ~ {round(daily['temperature_2m_max'][0])}℃

👔 穿搭参考:{get_cloth(temp)}
━━━━━━━━━━━━━━━━━━━━
"""
alert = ""
if "雨" in weather_text:
alert += "⚠️ 降雨天气,出行随身携带雨具\n"
if temp >= 30:
alert += "⚠️ 高温酷暑,做好防暑补水\n"
if temp <= 10:
alert += "⚠️ 气温偏低,增添衣物防寒\n"
msg += alert

msg += "\n📅 七日天气趋势预报\n"
today = datetime.now().date()

for i in range(7):
future_date = today + timedelta(days=i)
date_str = future_date.strftime("%m-%d")
week_str = week_list[future_date.weekday()]

min_t = round(daily["temperature_2m_min"][i])
max_t = round(daily["temperature_2m_max"][i])
day_weather = weather_map.get(daily["weather_code"][i], "🌫️ 未知")

msg += f"{date_str}({week_str}):{day_weather} {min_t}~{max_t}℃\n"

return msg.strip()

except Exception as e:
return f"❌ 气象数据获取异常:{str(e)}"

def send_wechat(msg):
try:
print("正在发送消息...")
pyperclip.copy(msg)
subprocess.Popen("start weixin://", shell=True)
time.sleep(1.5)
keyboard.send('ctrl+f')
time.sleep(0.3)
keyboard.write(WX_NAME)
time.sleep(0.8)
keyboard.send('enter')
time.sleep(0.8)
keyboard.send('ctrl+v')
time.sleep(0.4)
keyboard.send('enter')

print(f"✅ 消息推送成功 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
except Exception as e:
print(f"❌ 消息发送失败:{e}")

def morning_task():
content = get_weather(CITY)
print("=" * 40)
print(content)
print("=" * 40)
send_wechat(content)

if name == "main":
schedule.every().day.at(f"{SEND_HOUR:02d}:{SEND_MINUTE:02d}").do(morning_task)

print("===== 天气提醒程序启动完毕 =====")
print(f"每日固定推送时间:{SEND_HOUR}:{SEND_MINUTE}")
print("5秒后执行首次测试推送...")
time.sleep(5)
morning_task()

print("\n已进入定时等待模式...")
while True:
schedule.run_pending()
time.sleep(5)

4.将代码托管到码云Gitee上

https://gitee.com/qingfeng-pu/PythonProject9/blob/master/实验四天气通知.py

5.程序运行的视频

【实验四天气推送视频】https://www.bilibili.com/video/BV1S45F6RE9u?vd_source=96ed20e22115691cfb1d40d1df932cf2

6.实验中遇到的问题

问题一:一开始进行的是微信小程序的天气提醒,采用公众号进行消息发送,但公众号发送信息并不稳定
解决方案:将发送天气提醒直接发送给具体的人,并新增发送的内容,改变了公众号发送的单一,普通,让发送内容更加丰富多彩
问题二:一开始使用爬虫爬取中国天气网的天气数据,但大模型提示这种爬取会违反某些网站的协议
解决方案:将爬虫爬取替换为调用 Open-Meteo 免费 API,先通过城市名获取经纬度,再根据经纬度获取精准气象数据,有效解决该问题

7.课程总结

7.1知识点总结
Python课程按照从基础入门到综合实战的体系全面展开,覆盖Python程序设计核心知识与实用开发技能。课程首先介绍Python跨平台、解释型、面向对象、动态类型的语言特点,以及变量、数据类型、基本运算、循环语句等基础语法,讲解列表、元组、字典、集合四类序列结构的用法,字符串拼接与正则表达式的模式匹配功能,并说明使用pyInstaller实现程序打包的方法。随后进入面向对象程序设计核心内容,讲解类与对象的关系、__init__构造方法的作用、封装特性中单下划线与双下划线的访问控制规则,以及继承、方法重写、super()调用父类方法和多态三大核心特性。接下来学习模块与包的使用方法,掌握模块导入、别名使用、__name__变量的作用,同时系统学习异常处理机制,包括常见异常类型、try-except-finally捕获处理、raise抛出异常与assert断言调试。之后讲解文件与目录操作,掌握文件打开、读写、关闭及with语句的使用,熟练运用os模块实现目录创建、删除、遍历等操作;再学习数据库操作,以SQLite3嵌入式数据库与MySQL为主,实现数据库连接、游标创建及数据增删改查功能。随后进入网络编程部分,学习Socket套接字原理,掌握TCP与UDP两种通信模式,以及服务端绑定、监听、接收连接和客户端连接、数据收发的完整流程。最后学习网络爬虫技术,掌握urllib、requests等网络请求库,通过设置请求头、处理超时、使用代理等方式应对反爬机制,并了解Scrapy、PySpider等主流爬虫框架。同时将类与对象封装、文件持久化存储、业务逻辑处理相结合,完整覆盖Python从基础语法到文件、数据库、网络通信、自动化爬虫的全栈知识点,兼顾理论理解与工程实践,帮助掌握实用的Python开发能力。
7.2心得体会
在选择python这门课之前,认为所有关于计算机语言的科目都比较枯燥无味,但在上课之后,发现老师的讲法形象生动,能将讲授内容与现实生活紧密相连,现在还能记得关于“蛋炒饭”和“盖浇饭”的区别,同时通过该课程的学习,培养了我自主解决问题的能力,从创建Gitee仓库到正确上传,从pycharm的注册到pycharm的配置,以及实验中遇到的种种问题,通过大模型解答并进行自我学习,有效提高了我在计算机这类学科上的解决问题的能力,经过半学期的学习,受益匪浅,正所谓“人生苦短,我学python”,这门课让我感受到了来自计算机语言的魅力。最后祝王老师工作顺利,身体健康!

posted @ 2026-06-08 18:05  花间且晚钟  阅读(10)  评论(0)    收藏  举报