怎么用Python定时发送天气邮件

发布时间:2022-02-07 14:42:29 作者:iii
来源:亿速云 阅读:168
# 怎么用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

1.2 获取天气API

我们需要一个提供天气数据的API服务。这里推荐使用和风天气(免费版足够个人使用):

  1. 注册和风天气开发者账号(https://dev.heweather.com/)
  2. 创建应用,获取API Key
  3. 查看API文档,了解请求格式

1.3 邮箱设置

为了能够发送邮件,你需要:

  1. 一个支持SMTP的邮箱账号(如QQ邮箱、163邮箱等)
  2. 开启SMTP服务(通常在邮箱设置中)
  3. 获取SMTP授权码(不是邮箱密码)

二、获取天气数据

2.1 请求天气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)}"

2.2 处理天气数据

我们可以对返回的天气数据进行进一步处理,使其更符合邮件内容的需求:

def format_weather_data(raw_weather):
    """
    格式化天气数据为更友好的显示
    """
    # 这里可以添加更多的格式化逻辑
    return raw_weather.replace(" ", "").strip()

三、发送电子邮件

3.1 配置邮件参数

我们需要设置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授权码

3.2 构建邮件发送函数

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

3.3 邮件内容美化

我们可以使用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')
    
    # 其余代码保持不变
    ...

四、定时任务设置

4.1 使用schedule库

我们可以使用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)  # 每分钟检查一次

4.2 使用系统定时任务

除了使用Python内部的定时任务,我们还可以使用系统的定时任务功能:

Windows系统:

  1. 打开”任务计划程序”
  2. 创建基本任务
  3. 设置触发器(每天7:00)
  4. 操作选择”启动程序”,指向你的Python脚本

Linux系统:

使用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()

六、进阶功能

6.1 多城市支持

修改配置和函数,支持多个城市的天气报告:

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

6.2 异常处理与重试

增加更健壮的异常处理和重试机制:

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

6.3 日志记录

添加日志记录功能,便于问题排查:

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)}")

七、常见问题与解决方案

7.1 邮件发送失败

可能原因及解决方案: 1. SMTP配置错误:检查主机、端口、用户名和授权码 2. 网络问题:确保可以访问SMTP服务器 3. 邮箱限制:部分邮箱对发送频率有限制

7.2 天气API无法访问

可能原因: 1. API Key无效或过期 2. 请求次数超过限制 3. 城市名称不正确

解决方案: 1. 检查和风天气API文档 2. 确认城市ID或名称正确 3. 考虑添加缓存机制减少API调用

7.3 定时任务不执行

检查点: 1. 确保Python脚本持续运行 2. 检查系统时间是否正确 3. 对于crontab,检查日志输出

八、总结

本文详细介绍了如何使用Python实现定时发送天气邮件的功能。通过整合天气API、SMTP邮件发送和定时任务调度,我们构建了一个完整的自动化解决方案。这个项目不仅实用,也是学习Python网络编程和自动化任务的好例子。

你可以在此基础上进一步扩展: - 添加天气预报(未来几天) - 支持邮件模板自定义 - 增加用户订阅功能 - 开发Web界面进行配置管理

希望本文对你有所帮助,祝你编程愉快!


字数统计:约4600字 “`

推荐阅读:
  1. Python定时发送天气预报邮件
  2. 如何实现定时发送邮件

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python

上一篇:JSON.toJSONString()空字段不忽略怎么修改

下一篇:怎么解决JSON.toJSONString()首字母大小写的问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》