您好,登录后才能下订单哦!
# 怎么用Python定时发送天气邮件
## 前言
在现代生活中,定时获取天气信息并通过邮件自动发送是一项非常实用的功能。无论是个人日常安排、出行计划,还是企业运营、项目管理,都需要及时了解天气状况。本文将详细介绍如何使用Python实现定时发送天气邮件的功能,涵盖从获取天气数据到邮件发送,再到定时任务调度的完整流程。
通过阅读本文,你将学会:
1. 使用Python获取实时天气数据
2. 使用SMTP协议发送电子邮件
3. 设置定时任务自动执行脚本
4. 处理可能遇到的常见问题
## 一、准备工作
### 1.1 环境配置
在开始之前,请确保你的系统已经安装了Python(建议3.6+版本)。我们将使用以下Python库:
```python
import requests # 用于获取天气API数据
import smtplib # 发送邮件
from email.mime.text import MIMEText # 构建邮件内容
from email.header import Header # 邮件头信息
import schedule # 定时任务调度
import time # 时间处理
可以通过pip安装这些库:
pip install requests schedule
我们需要一个提供天气数据的API服务。这里推荐使用和风天气(免费版足够个人使用):
为了能够发送邮件,你需要:
首先我们编写获取天气数据的函数:
def get_weather(city, api_key):
"""
获取指定城市的天气数据
:param city: 城市名称
:param api_key: 和风天气API Key
:return: 格式化后的天气信息字符串
"""
# 和风天气API地址
url = f"https://devapi.qweather.com/v7/weather/now?location={city}&key={api_key}"
try:
response = requests.get(url)
data = response.json()
if data["code"] == "200":
weather_info = data["now"]
return f"""
城市: {city}
天气状况: {weather_info['text']}
温度: {weather_info['temp']}°C
体感温度: {weather_info['feelsLike']}°C
风向: {weather_info['windDir']}
风力等级: {weather_info['windScale']}级
相对湿度: {weather_info['humidity']}%
降水量: {weather_info['precip']}mm
能见度: {weather_info['vis']}km
更新时间: {weather_info['obsTime']}
"""
else:
return f"获取天气失败: {data['message']}"
except Exception as e:
return f"请求天气API出错: {str(e)}"
我们可以对返回的天气数据进行进一步处理,使其更符合邮件内容的需求:
def format_weather_data(raw_weather):
"""
格式化天气数据为更友好的显示
"""
# 这里可以添加更多的格式化逻辑
return raw_weather.replace(" ", "").strip()
我们需要设置SMTP服务器的相关信息:
# 邮件配置
EML_HOST = "smtp.qq.com" # QQ邮箱SMTP服务器
EML_PORT = 465 # SSL端口
EML_USER = "your_email@qq.com" # 发件人邮箱
EML_PWD = "your_smtp_auth_code" # SMTP授权码
def send_email(subject, content, to_addrs):
"""
发送电子邮件
:param subject: 邮件主题
:param content: 邮件内容
:param to_addrs: 收件人列表
"""
# 构建邮件内容
message = MIMEText(content, 'plain', 'utf-8')
message['From'] = Header("天气小助手", 'utf-8')
message['To'] = Header(",".join(to_addrs), 'utf-8')
message['Subject'] = Header(subject, 'utf-8')
try:
# 连接SMTP服务器
smtp_obj = smtplib.SMTP_SSL(EML_HOST, EML_PORT)
smtp_obj.login(EML_USER, EML_PWD)
smtp_obj.sendmail(EML_USER, to_addrs, message.as_string())
print("邮件发送成功")
return True
except smtplib.SMTPException as e:
print(f"邮件发送失败: {str(e)}")
return False
finally:
try:
smtp_obj.quit()
except:
pass
我们可以使用HTML格式的邮件内容,使其更加美观:
def create_html_content(weather_info):
"""
创建HTML格式的邮件内容
"""
html = f"""
<html>
<body>
<h2 style="color: #1e88e5;">每日天气报告</h2>
<div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px;">
<pre>{weather_info}</pre>
</div>
<p style="color: #757575; font-size: 12px;">
本邮件由Python自动发送,请勿直接回复。
</p>
</body>
</html>
"""
return html
修改send_email函数以支持HTML:
def send_email(subject, content, to_addrs, is_html=False):
"""
发送电子邮件(支持HTML)
"""
# 根据is_html参数选择内容类型
if is_html:
message = MIMEText(content, 'html', 'utf-8')
else:
message = MIMEText(content, 'plain', 'utf-8')
# 其余代码保持不变
...
我们可以使用Python的schedule库来设置定时任务:
def job():
print("开始执行天气邮件发送任务...")
city = "北京"
api_key = "your_heweather_api_key"
# 获取天气
weather_raw = get_weather(city, api_key)
weather_info = format_weather_data(weather_raw)
# 发送邮件
subject = f"{city}今日天气报告"
content = create_html_content(weather_info)
to_addrs = ["recipient1@example.com", "recipient2@example.com"]
send_email(subject, content, to_addrs, is_html=True)
# 设置每天早上7点执行
schedule.every().day.at("07:00").do(job)
# 保持程序运行
while True:
schedule.run_pending()
time.sleep(60) # 每分钟检查一次
除了使用Python内部的定时任务,我们还可以使用系统的定时任务功能:
使用crontab添加定时任务:
0 7 * * * /usr/bin/python3 /path/to/your_script.py
import requests
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import schedule
import time
# 配置信息
CONFIG = {
"email": {
"host": "smtp.qq.com",
"port": 465,
"user": "your_email@qq.com",
"pwd": "your_smtp_auth_code"
},
"weather": {
"api_key": "your_heweather_api_key",
"city": "北京"
},
"recipients": ["recipient1@example.com", "recipient2@example.com"]
}
def get_weather(city, api_key):
"""获取天气数据"""
url = f"https://devapi.qweather.com/v7/weather/now?location={city}&key={api_key}"
try:
response = requests.get(url)
data = response.json()
if data["code"] == "200":
return data["now"]
return None
except Exception as e:
print(f"获取天气出错: {str(e)}")
return None
def format_weather(weather_data, city):
"""格式化天气信息"""
if not weather_data:
return "获取天气信息失败"
return f"""
<html>
<body>
<h2 style="color: #1e88e5;">{city}天气报告</h2>
<table style="border-collapse: collapse; width: 100%;">
<tr style="background-color: #f5f5f5;">
<td style="padding: 8px; border: 1px solid #ddd;">天气状况</td>
<td style="padding: 8px; border: 1px solid #ddd;">{weather_data['text']}</td>
</tr>
<!-- 更多天气信息行 -->
</table>
<p style="color: #757575; font-size: 12px;">
更新时间: {weather_data['obsTime']}<br>
本邮件由Python自动发送
</p>
</body>
</html>
"""
def send_email(subject, content, to_addrs):
"""发送邮件"""
message = MIMEText(content, 'html', 'utf-8')
message['From'] = Header("天气助手", 'utf-8')
message['To'] = Header(",".join(to_addrs), 'utf-8')
message['Subject'] = Header(subject, 'utf-8')
try:
smtp = smtplib.SMTP_SSL(CONFIG['email']['host'], CONFIG['email']['port'])
smtp.login(CONFIG['email']['user'], CONFIG['email']['pwd'])
smtp.sendmail(CONFIG['email']['user'], to_addrs, message.as_string())
print("邮件发送成功")
return True
except Exception as e:
print(f"邮件发送失败: {str(e)}")
return False
finally:
try:
smtp.quit()
except:
pass
def weather_report_job():
"""定时任务"""
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 开始执行天气邮件发送...")
# 获取天气
weather_data = get_weather(CONFIG['weather']['city'], CONFIG['weather']['api_key'])
content = format_weather(weather_data, CONFIG['weather']['city'])
# 发送邮件
subject = f"{CONFIG['weather']['city']}每日天气报告 - {time.strftime('%Y-%m-%d')}"
send_email(subject, content, CONFIG['recipients'])
def main():
# 设置定时任务
schedule.every().day.at("07:00").do(weather_report_job)
print("天气邮件服务已启动,等待执行...")
while True:
schedule.run_pending()
time.sleep(60)
if __name__ == "__main__":
main()
修改配置和函数,支持多个城市的天气报告:
CONFIG = {
"cities": ["北京", "上海", "广州"],
# 其他配置...
}
def multi_city_report():
for city in CONFIG['cities']:
weather_data = get_weather(city, CONFIG['weather']['api_key'])
content = format_weather(weather_data, city)
subject = f"{city}天气报告 - {time.strftime('%Y-%m-%d')}"
send_email(subject, content, CONFIG['recipients'])
time.sleep(1) # 避免频繁请求API
增加更健壮的异常处理和重试机制:
def send_email_with_retry(subject, content, to_addrs, max_retries=3):
"""带重试机制的邮件发送"""
for attempt in range(max_retries):
if send_email(subject, content, to_addrs):
return True
if attempt < max_retries - 1:
print(f"等待5秒后重试... ({attempt + 1}/{max_retries})")
time.sleep(5)
return False
添加日志记录功能,便于问题排查:
import logging
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename='weather_email.log'
)
logger = logging.getLogger(__name__)
# 在代码中使用logger替代print
logger.info("邮件发送成功")
logger.error(f"邮件发送失败: {str(e)}")
可能原因及解决方案: 1. SMTP配置错误:检查主机、端口、用户名和授权码 2. 网络问题:确保可以访问SMTP服务器 3. 邮箱限制:部分邮箱对发送频率有限制
可能原因: 1. API Key无效或过期 2. 请求次数超过限制 3. 城市名称不正确
解决方案: 1. 检查和风天气API文档 2. 确认城市ID或名称正确 3. 考虑添加缓存机制减少API调用
检查点: 1. 确保Python脚本持续运行 2. 检查系统时间是否正确 3. 对于crontab,检查日志输出
本文详细介绍了如何使用Python实现定时发送天气邮件的功能。通过整合天气API、SMTP邮件发送和定时任务调度,我们构建了一个完整的自动化解决方案。这个项目不仅实用,也是学习Python网络编程和自动化任务的好例子。
你可以在此基础上进一步扩展: - 添加天气预报(未来几天) - 支持邮件模板自定义 - 增加用户订阅功能 - 开发Web界面进行配置管理
希望本文对你有所帮助,祝你编程愉快!
字数统计:约4600字 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。