欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Python編寫一個(gè)每日天氣提醒

 更新時(shí)間:2025年10月27日 09:06:06   作者:閑人編程  
在這個(gè)快節(jié)奏的時(shí)代,一個(gè)小小的貼心舉動(dòng)往往能帶來意想不到的溫暖,本文就將教你如何使用Python構(gòu)建一個(gè)自動(dòng)化的每日天氣提醒系統(tǒng),有需要的可以參考下

1. 引言

在這個(gè)快節(jié)奏的時(shí)代,一個(gè)小小的貼心舉動(dòng)往往能帶來意想不到的溫暖。想象一下,每天清晨,你的女朋友都能收到一條溫馨的天氣提醒,不僅包含準(zhǔn)確的天氣信息,還有你親自編寫的暖心提示——這樣的關(guān)懷是不是很讓人心動(dòng)?

本文就將教你如何使用Python構(gòu)建一個(gè)自動(dòng)化的每日天氣提醒系統(tǒng)。這個(gè)系統(tǒng)不僅實(shí)用,更重要的是它融入了你的個(gè)人情感,讓技術(shù)變得有溫度。無論你是編程新手還是有經(jīng)驗(yàn)的開發(fā)者,都能通過本文學(xué)會(huì)如何將技術(shù)轉(zhuǎn)化為貼心的浪漫工具。

2. 系統(tǒng)設(shè)計(jì)與功能規(guī)劃

2.1 系統(tǒng)架構(gòu)設(shè)計(jì)

在開始編碼之前,讓我們先來規(guī)劃整個(gè)系統(tǒng)的架構(gòu)。我們的天氣提醒系統(tǒng)需要包含以下幾個(gè)核心模塊:

2.2 核心功能特性

我們的天氣提醒系統(tǒng)將實(shí)現(xiàn)以下特色功能:

  • 精準(zhǔn)天氣信息:獲取實(shí)時(shí)天氣、溫度、濕度、風(fēng)速等詳細(xì)信息
  • 智能穿衣建議:根據(jù)溫度自動(dòng)生成合適的穿衣建議
  • 個(gè)性化關(guān)懷提示:結(jié)合天氣情況提供貼心的生活建議
  • 多平臺(tái)支持:支持微信、郵件、短信等多種發(fā)送方式
  • 定時(shí)發(fā)送:在指定時(shí)間自動(dòng)發(fā)送提醒
  • 異常處理:網(wǎng)絡(luò)異常或服務(wù)不可用時(shí)的備用方案

2.3 技術(shù)選型

  • 天氣數(shù)據(jù)源:使用和風(fēng)天氣、OpenWeatherMap等免費(fèi)API
  • 消息發(fā)送:使用SMTP協(xié)議發(fā)送郵件,或itchat庫發(fā)送微信
  • 定時(shí)任務(wù):使用APScheduler庫管理定時(shí)任務(wù)
  • 數(shù)據(jù)存儲(chǔ):使用SQLite存儲(chǔ)配置和歷史記錄
  • 配置管理:使用配置文件或環(huán)境變量管理敏感信息

3. 準(zhǔn)備工作與環(huán)境配置

3.1 申請(qǐng)?zhí)鞖釧PI服務(wù)

首先,我們需要選擇一個(gè)天氣數(shù)據(jù)提供商。這里以和風(fēng)天氣(免費(fèi)版)為例:

  • 訪問和風(fēng)天氣官網(wǎng)注冊(cè)賬號(hào)
  • 創(chuàng)建應(yīng)用,獲取API Key
  • 了解API調(diào)用方式和返回?cái)?shù)據(jù)格式

其他可選天氣服務(wù):

  • OpenWeatherMap(免費(fèi)版有限制)
  • 心知天氣
  • 阿里云天氣API

3.2 安裝必要的Python庫

pip install requests apscheduler python-dotenv sqlalchemy

如果需要微信支持,還需要安裝:

pip install itchat-uos

3.3 環(huán)境變量配置

創(chuàng)建.env文件來存儲(chǔ)敏感信息:

# 天氣API配置
WEATHER_API_KEY=你的和風(fēng)天氣API_KEY
WEATHER_CITY=北京

# 郵箱配置(用于發(fā)送郵件提醒)
EMAIL_HOST=smtp.qq.com
EMAIL_PORT=587
EMAIL_USER=你的郵箱@qq.com
EMAIL_PASSWORD=你的郵箱授權(quán)碼

# 接收方配置
RECIPIENT_EMAIL=女朋友的郵箱@gmail.com
RECIPIENT_NAME=親愛的

4. 核心模塊實(shí)現(xiàn)

4.1 天氣數(shù)據(jù)獲取模塊

import requests
import json
from datetime import datetime, timedelta
import logging
from typing import Dict, List, Optional

class WeatherService:
    """天氣服務(wù)類,負(fù)責(zé)獲取和處理天氣數(shù)據(jù)"""
    
    def __init__(self, api_key: str, city: str):
        """
        初始化天氣服務(wù)
        
        Args:
            api_key: 和風(fēng)天氣API Key
            city: 城市名稱
        """
        self.api_key = api_key
        self.city = city
        self.base_url = "https://devapi.qweather.com/v7"
        self.logger = logging.getLogger(__name__)
        
    def get_city_location(self) -> Optional[Dict]:
        """獲取城市位置信息(城市ID、坐標(biāo)等)"""
        url = f"{self.base_url}/weather/now"
        params = {
            'location': self.city,
            'key': self.api_key
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data['code'] == '200':
                # 從返回?cái)?shù)據(jù)中提取位置信息
                location_info = {
                    'city': data.get('location', [{}])[0].get('name', self.city),
                    'id': data.get('location', [{}])[0].get('id', ''),
                    'lat': data.get('location', [{}])[0].get('lat', ''),
                    'lon': data.get('location', [{}])[0].get('lon', '')
                }
                return location_info
            else:
                self.logger.error(f"獲取位置信息失敗: {data.get('message', '未知錯(cuò)誤')}")
                return None
                
        except requests.exceptions.RequestException as e:
            self.logger.error(f"網(wǎng)絡(luò)請(qǐng)求失敗: {str(e)}")
            return None
        except Exception as e:
            self.logger.error(f"獲取位置信息異常: {str(e)}")
            return None
    
    def get_current_weather(self) -> Optional[Dict]:
        """獲取當(dāng)前天氣情況"""
        url = f"{self.base_url}/weather/now"
        params = {
            'location': self.city,
            'key': self.api_key,
            'lang': 'zh'  # 中文返回
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data['code'] == '200':
                weather_data = data['now']
                return {
                    'temp': weather_data.get('temp', 'N/A'),  # 溫度
                    'feels_like': weather_data.get('feelsLike', 'N/A'),  # 體感溫度
                    'text': weather_data.get('text', 'N/A'),  # 天氣狀況文字
                    'wind_scale': weather_data.get('windScale', 'N/A'),  # 風(fēng)力等級(jí)
                    'wind_dir': weather_data.get('windDir', 'N/A'),  # 風(fēng)向
                    'humidity': weather_data.get('humidity', 'N/A'),  # 濕度
                    'precip': weather_data.get('precip', '0'),  # 降水量
                    'vis': weather_data.get('vis', 'N/A'),  # 能見度
                    'pressure': weather_data.get('pressure', 'N/A'),  # 氣壓
                    'update_time': weather_data.get('obsTime', '')  # 更新時(shí)間
                }
            else:
                self.logger.error(f"獲取當(dāng)前天氣失敗: {data.get('message', '未知錯(cuò)誤')}")
                return None
                
        except requests.exceptions.RequestException as e:
            self.logger.error(f"獲取當(dāng)前天氣網(wǎng)絡(luò)請(qǐng)求失敗: {str(e)}")
            return None
        except Exception as e:
            self.logger.error(f"獲取當(dāng)前天氣異常: {str(e)}")
            return None
    
    def get_daily_forecast(self, days: int = 3) -> Optional[List[Dict]]:
        """獲取多日天氣預(yù)報(bào)"""
        url = f"{self.base_url}/weather/{days}d"
        params = {
            'location': self.city,
            'key': self.api_key,
            'lang': 'zh'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data['code'] == '200':
                forecast_list = []
                for day_data in data.get('daily', []):
                    forecast = {
                        'date': day_data.get('fxDate', ''),
                        'temp_max': day_data.get('tempMax', 'N/A'),
                        'temp_min': day_data.get('tempMin', 'N/A'),
                        'text_day': day_data.get('textDay', 'N/A'),
                        'text_night': day_data.get('textNight', 'N/A'),
                        'wind_scale_day': day_data.get('windScaleDay', 'N/A'),
                        'humidity': day_data.get('humidity', 'N/A'),
                        'precip': day_data.get('precip', '0'),
                        'uv_index': day_data.get('uvIndex', 'N/A')
                    }
                    forecast_list.append(forecast)
                return forecast_list
            else:
                self.logger.error(f"獲取天氣預(yù)報(bào)失敗: {data.get('message', '未知錯(cuò)誤')}")
                return None
                
        except requests.exceptions.RequestException as e:
            self.logger.error(f"獲取天氣預(yù)報(bào)網(wǎng)絡(luò)請(qǐng)求失敗: {str(e)}")
            return None
        except Exception as e:
            self.logger.error(f"獲取天氣預(yù)報(bào)異常: {str(e)}")
            return None
    
    def get_weather_warning(self) -> Optional[List[Dict]]:
        """獲取天氣預(yù)警信息"""
        url = f"{self.base_url}/warning/now"
        params = {
            'location': self.city,
            'key': self.api_key,
            'lang': 'zh'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data['code'] == '200':
                warnings = []
                for warning in data.get('warning', []):
                    warning_info = {
                        'type': warning.get('type', ''),
                        'level': warning.get('level', ''),
                        'title': warning.get('title', ''),
                        'text': warning.get('text', '')
                    }
                    warnings.append(warning_info)
                return warnings
            else:
                # 沒有預(yù)警信息是正常情況
                return []
                
        except Exception as e:
            self.logger.warning(f"獲取天氣預(yù)警信息失敗: {str(e)}")
            return []

4.2 智能分析與建議生成模塊

class WeatherAnalyzer:
    """天氣分析器,根據(jù)天氣數(shù)據(jù)生成智能建議"""
    
    def __init__(self):
        self.advice_templates = {
            'dressing': self._get_dressing_advice,
            'umbrella': self._get_umbrella_advice,
            'outdoor': self._get_outdoor_advice,
            'health': self._get_health_advice,
            'travel': self._get_travel_advice
        }
    
    def analyze_temperature(self, temp: int) -> Dict[str, str]:
        """分析溫度并給出建議"""
        temp = int(temp)
        
        if temp >= 30:
            level = "炎熱"
            feeling = "今天天氣炎熱,注意防暑降溫"
        elif temp >= 25:
            level = "溫暖"
            feeling = "今天天氣溫暖,適合戶外活動(dòng)"
        elif temp >= 15:
            level = "舒適"
            feeling = "今天天氣舒適,是出行的好日子"
        elif temp >= 5:
            level = "涼爽"
            feeling = "今天天氣涼爽,記得適當(dāng)添衣"
        elif temp >= 0:
            level = "寒冷"
            feeling = "今天天氣寒冷,注意保暖"
        else:
            level = "嚴(yán)寒"
            feeling = "今天天氣嚴(yán)寒,盡量減少外出"
            
        return {'level': level, 'feeling': feeling}
    
    def _get_dressing_advice(self, temp: int, weather_text: str) -> str:
        """生成穿衣建議"""
        temp = int(temp)
        
        if "雨" in weather_text:
            rain_note = "有雨,建議穿防水的衣物"
        else:
            rain_note = ""
            
        if temp >= 28:
            return f"?? 輕薄夏裝(短袖、裙子){rain_note}"
        elif temp >= 24:
            return f"?? 夏季服裝(短袖、薄長褲){rain_note}"
        elif temp >= 18:
            return f"?? 春秋過渡裝(長袖T恤、薄外套){rain_note}"
        elif temp >= 12:
            return f"?? 春秋裝(長袖、薄毛衣、外套){rain_note}"
        elif temp >= 6:
            return f"?? 初冬裝(毛衣、厚外套){rain_note}"
        elif temp >= 0:
            return f"?? 冬裝(羽絨服、厚毛衣){rain_note}"
        else:
            return f"?? 厚冬裝(加厚羽絨服、保暖內(nèi)衣){rain_note}"
    
    def _get_umbrella_advice(self, weather_text: str, precip: float) -> str:
        """生成雨具建議"""
        precip = float(precip)
        
        if "雨" in weather_text or precip > 0:
            if precip > 10:
                return "?? 今天有大雨,一定要帶傘,建議穿雨鞋"
            elif precip > 5:
                return "? 今天有中雨,記得帶傘"
            else:
                return "??? 今天有小雨,建議帶傘"
        else:
            return "?? 今天無雨,可以不用帶傘"
    
    def _get_outdoor_advice(self, weather_text: str, temp: int, wind_scale: str) -> str:
        """生成戶外活動(dòng)建議"""
        temp = int(temp)
        
        advice = []
        
        # 溫度適宜性
        if 18 <= temp <= 26:
            advice.append("今天的溫度非常適合戶外活動(dòng)")
        elif temp > 30:
            advice.append("天氣炎熱,建議在陰涼處活動(dòng)")
        elif temp < 5:
            advice.append("天氣較冷,戶外活動(dòng)請(qǐng)注意保暖")
        
        # 天氣狀況
        if "晴" in weather_text:
            advice.append("陽光很好,適合散步和運(yùn)動(dòng)")
        elif "雨" in weather_text:
            advice.append("有雨,建議室內(nèi)活動(dòng)")
        elif "云" in weather_text:
            advice.append("多云天氣,適合各種戶外活動(dòng)")
        elif "雪" in weather_text:
            advice.append("下雪天,注意防滑")
            
        # 風(fēng)力影響
        if int(wind_scale) >= 6:
            advice.append("今天風(fēng)較大,注意安全")
            
        return "。".join(advice) if advice else "今天天氣平穩(wěn),按計(jì)劃活動(dòng)即可"
    
    def _get_health_advice(self, temp: int, humidity: int, uv_index: str) -> str:
        """生成健康建議"""
        temp = int(temp)
        humidity = int(humidity)
        
        advice = []
        
        # 溫度相關(guān)
        if temp >= 30:
            advice.append("天氣炎熱,注意補(bǔ)充水分,預(yù)防中暑")
        elif temp <= 0:
            advice.append("天氣寒冷,注意保暖,預(yù)防感冒")
            
        # 濕度相關(guān)
        if humidity >= 80:
            advice.append("濕度較高,注意防潮")
        elif humidity <= 30:
            advice.append("空氣干燥,注意保濕")
            
        # 紫外線
        if uv_index in ['5', '6', '7']:
            advice.append("紫外線中等,建議使用防曬霜")
        elif uv_index in ['8', '9', '10']:
            advice.append("紫外線強(qiáng),需要做好防曬措施")
        elif uv_index in ['11', '12', '13', '14', '15']:
            advice.append("紫外線很強(qiáng),盡量避免長時(shí)間在陽光下")
            
        return "。".join(advice) if advice else "今天天氣條件對(duì)健康影響較小"
    
    def _get_travel_advice(self, weather_text: str, vis: str) -> str:
        """生成出行建議"""
        advice = []
        
        if "雨" in weather_text:
            advice.append("雨天路滑,開車請(qǐng)減速慢行")
        elif "雪" in weather_text:
            advice.append("雪天路滑,建議使用公共交通工具")
        elif "霧" in weather_text:
            advice.append("有霧,能見度較低,注意行車安全")
            
        if vis and int(vis) < 1:
            advice.append("能見度很低,出行請(qǐng)?zhí)貏e注意安全")
        elif vis and int(vis) < 5:
            advice.append("能見度一般,小心駕駛")
            
        return "。".join(advice) if advice else "今天出行條件良好"
    
    def generate_comprehensive_advice(self, weather_data: Dict) -> Dict[str, str]:
        """生成綜合建議"""
        temp = int(weather_data.get('temp', 20))
        weather_text = weather_data.get('text', '')
        precip = float(weather_data.get('precip', 0))
        wind_scale = weather_data.get('wind_scale', '1')
        humidity = int(weather_data.get('humidity', 50))
        uv_index = weather_data.get('uv_index', '3')
        vis = weather_data.get('vis', '10')
        
        return {
            'temperature_analysis': self.analyze_temperature(temp),
            'dressing': self._get_dressing_advice(temp, weather_text),
            'umbrella': self._get_umbrella_advice(weather_text, precip),
            'outdoor': self._get_outdoor_advice(weather_text, temp, wind_scale),
            'health': self._get_health_advice(temp, humidity, uv_index),
            'travel': self._get_travel_advice(weather_text, vis)
        }

4.3 個(gè)性化消息生成模塊

import random
from datetime import datetime

class MessageGenerator:
    """消息生成器,創(chuàng)建個(gè)性化的天氣提醒消息"""
    
    def __init__(self, recipient_name: str):
        self.recipient_name = recipient_name
        self.greetings = [
            "早安,{}!新的一天開始啦",
            "早上好,{}!愿你有美好的一天",
            "{},醒來了嗎?來看看今天的天氣吧",
            "嗨,{}!今天也要加油哦",
            "{},新的一天充滿新的可能"
        ]
        
        self.closing_remarks = [
            "記得按時(shí)吃飯,愛你??",
            "不管天氣如何,我的關(guān)心永遠(yuǎn)不變??",
            "今天也要開開心心的哦??",
            "記得想我,就像我想你一樣??",
            "愿你的一天像陽光一樣燦爛?"
        ]
        
        self.special_date_remarks = {
            'anniversary': "今天是我們的紀(jì)念日,晚上有驚喜哦??",
            'birthday': "生日快樂!我的小公主??",
            'valentine': "情人節(jié)快樂!我的愛人??",
            'weekend': "周末愉快!我們出去約會(huì)吧??"
        }
    
    def _check_special_date(self) -> Optional[str]:
        """檢查是否是特殊日期"""
        today = datetime.now()
        
        # 這里可以添加你們的特殊日期
        special_dates = {
            # 'anniversary': datetime(2024, 2, 14),  # 紀(jì)念日示例
            # 'birthday': datetime(2024, 3, 8),      # 生日示例
        }
        
        for occasion, date in special_dates.items():
            if today.month == date.month and today.day == date.day:
                return occasion
                
        # 檢查周末
        if today.weekday() >= 5:  # 5=周六, 6=周日
            return 'weekend'
            
        return None
    
    def generate_message(self, weather_data: Dict, advice_data: Dict, 
                        forecast_data: List[Dict] = None) -> str:
        """生成完整的天氣提醒消息"""
        
        # 問候語
        greeting = random.choice(self.greetings).format(self.recipient_name)
        
        # 當(dāng)前天氣摘要
        current_temp = weather_data.get('temp', 'N/A')
        weather_text = weather_data.get('text', 'N/A')
        temp_analysis = advice_data['temperature_analysis']
        
        weather_summary = (
            f"??? 當(dāng)前溫度:{current_temp}°C({temp_analysis['level']})\n"
            f"??? 天氣狀況:{weather_text}\n"
            f"?? 體感溫度:{weather_data.get('feels_like', 'N/A')}°C\n"
            f"?? 濕度:{weather_data.get('humidity', 'N/A')}%\n"
            f"??? 風(fēng)力:{weather_data.get('wind_scale', 'N/A')}級(jí) {weather_data.get('wind_dir', '')}"
        )
        
        # 生活建議
        advice_section = (
            f"\n?? 今日生活建議:\n"
            f"{advice_data['dressing']}\n"
            f"{advice_data['umbrella']}\n"
            f"{advice_data['outdoor']}\n"
            f"{advice_data['health']}\n"
            f"{advice_data['travel']}"
        )
        
        # 天氣預(yù)報(bào)
        forecast_section = ""
        if forecast_data:
            forecast_section = "\n\n?? 未來三天預(yù)報(bào):\n"
            for i, forecast in enumerate(forecast_data[:3]):
                date_str = forecast['date'][5:]  # 只顯示月日
                day_name = "今天" if i == 0 else "明天" if i == 1 else "后天"
                forecast_section += (
                    f"{day_name}({date_str}):{forecast['text_day']},"
                    f"{forecast['temp_min']}~{forecast['temp_max']}°C\n"
                )
        
        # 預(yù)警信息
        warning_section = ""
        warnings = weather_data.get('warnings', [])
        if warnings:
            warning_section = "\n?? 天氣預(yù)警:\n"
            for warning in warnings:
                warning_section += f"{warning['title']}:{warning['text']}\n"
        
        # 特殊日期備注
        special_remark = ""
        special_occasion = self._check_special_date()
        if special_occasion:
            special_remark = f"\n?? {self.special_date_remarks[special_occasion]}"
        
        # 結(jié)束語
        closing = random.choice(self.closing_remarks)
        
        # 組合所有部分
        full_message = (
            f"{greeting}\n\n"
            f"{weather_summary}"
            f"{advice_section}"
            f"{forecast_section}"
            f"{warning_section}"
            f"{special_remark}\n\n"
            f"{closing}"
        )
        
        return full_message
    
    def generate_html_message(self, weather_data: Dict, advice_data: Dict,
                            forecast_data: List[Dict] = None) -> str:
        """生成HTML格式的消息(用于郵件)"""
        # 這里實(shí)現(xiàn)HTML格式的消息生成
        # 由于篇幅限制,具體實(shí)現(xiàn)略
        pass

4.4 消息發(fā)送模塊

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging
from typing import List

class MessageSender:
    """消息發(fā)送器,支持多種發(fā)送方式"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def send_email(self, recipient: str, subject: str, content: str,
                  smtp_host: str, smtp_port: int, 
                  username: str, password: str) -> bool:
        """通過郵件發(fā)送消息"""
        
        try:
            # 創(chuàng)建郵件對(duì)象
            msg = MIMEMultipart()
            msg['From'] = username
            msg['To'] = recipient
            msg['Subject'] = subject
            
            # 添加文本內(nèi)容
            text_part = MIMEText(content, 'plain', 'utf-8')
            msg.attach(text_part)
            
            # 發(fā)送郵件
            with smtplib.SMTP(smtp_host, smtp_port) as server:
                server.starttls()  # 啟用TLS加密
                server.login(username, password)
                server.send_message(msg)
                
            self.logger.info(f"郵件發(fā)送成功:{recipient}")
            return True
            
        except Exception as e:
            self.logger.error(f"郵件發(fā)送失?。簕str(e)}")
            return False
    
    def send_wechat(self, content: str) -> bool:
        """通過微信發(fā)送消息(需要安裝itchat-uos)"""
        try:
            import itchat
            
            # 查找指定備注的好友
            friends = itchat.search_friends(name='女朋友的備注名')  # 修改為實(shí)際備注
            if friends:
                friend = friends[0]
                itchat.send(content, toUserName=friend['UserName'])
                self.logger.info("微信消息發(fā)送成功")
                return True
            else:
                self.logger.error("未找到指定的微信好友")
                return False
                
        except ImportError:
            self.logger.error("未安裝itchat-uos,無法發(fā)送微信消息")
            return False
        except Exception as e:
            self.logger.error(f"微信消息發(fā)送失?。簕str(e)}")
            return False
    
    def send_sms(self, phone_number: str, content: str, 
                api_key: str = None) -> bool:
        """通過短信API發(fā)送消息"""
        # 這里可以實(shí)現(xiàn)短信發(fā)送功能
        # 需要接入短信服務(wù)商API
        self.logger.info("短信發(fā)送功能需要接入短信服務(wù)商API")
        return False
    
    def send_multiple_ways(self, content: str, config: Dict) -> bool:
        """嘗試多種方式發(fā)送消息"""
        success = False
        
        # 嘗試郵件發(fā)送
        if config.get('email_enabled', False):
            success = self.send_email(
                recipient=config['recipient_email'],
                subject=config.get('email_subject', '每日天氣提醒'),
                content=content,
                smtp_host=config['smtp_host'],
                smtp_port=config['smtp_port'],
                username=config['email_username'],
                password=config['email_password']
            )
        
        # 如果郵件發(fā)送失敗,嘗試微信
        if not success and config.get('wechat_enabled', False):
            success = self.send_wechat(content)
            
        return success

5. 系統(tǒng)集成與完整實(shí)現(xiàn)

現(xiàn)在我們將所有模塊整合在一起,創(chuàng)建一個(gè)完整的天氣提醒系統(tǒng):

#!/usr/bin/env python3
"""
每日天氣提醒系統(tǒng)
為你的女朋友提供貼心的天氣提醒服務(wù)
日期:2024年1月
"""

import os
import logging
from datetime import datetime
from dotenv import load_dotenv
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
import sqlite3
from typing import Dict, Any

# 導(dǎo)入自定義模塊
from weather_service import WeatherService
from weather_analyzer import WeatherAnalyzer
from message_generator import MessageGenerator
from message_sender import MessageSender

# 加載環(huán)境變量
load_dotenv()

class DailyWeatherReminder:
    """每日天氣提醒系統(tǒng)主類"""
    
    def __init__(self, config: Dict[str, Any] = None):
        """初始化系統(tǒng)"""
        
        # 配置日志
        self._setup_logging()
        
        # 加載配置
        self.config = config or self._load_config()
        
        # 初始化組件
        self.weather_service = WeatherService(
            api_key=self.config['weather_api_key'],
            city=self.config['city']
        )
        self.weather_analyzer = WeatherAnalyzer()
        self.message_generator = MessageGenerator(
            recipient_name=self.config['recipient_name']
        )
        self.message_sender = MessageSender()
        
        # 初始化數(shù)據(jù)庫
        self._init_database()
        
        # 初始化調(diào)度器
        self.scheduler = BackgroundScheduler()
        
        self.logger.info("每日天氣提醒系統(tǒng)初始化完成")
    
    def _setup_logging(self):
        """配置日志系統(tǒng)"""
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler('weather_reminder.log'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)
    
    def _load_config(self) -> Dict[str, Any]:
        """從環(huán)境變量加載配置"""
        return {
            'weather_api_key': os.getenv('WEATHER_API_KEY'),
            'city': os.getenv('WEATHER_CITY', '北京'),
            'smtp_host': os.getenv('EMAIL_HOST'),
            'smtp_port': int(os.getenv('EMAIL_PORT', 587)),
            'email_username': os.getenv('EMAIL_USER'),
            'email_password': os.getenv('EMAIL_PASSWORD'),
            'recipient_email': os.getenv('RECIPIENT_EMAIL'),
            'recipient_name': os.getenv('RECIPIENT_NAME', '親愛的'),
            'send_time': os.getenv('SEND_TIME', '07:30'),  # 默認(rèn)早上7:30發(fā)送
            'email_enabled': True,
            'wechat_enabled': False
        }
    
    def _init_database(self):
        """初始化SQLite數(shù)據(jù)庫"""
        self.conn = sqlite3.connect('weather_reminder.db', check_same_thread=False)
        cursor = self.conn.cursor()
        
        # 創(chuàng)建發(fā)送記錄表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS send_history (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                send_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                success BOOLEAN,
                message TEXT,
                weather_data TEXT
            )
        ''')
        
        self.conn.commit()
    
    def _log_send_attempt(self, success: bool, message: str, weather_data: Dict):
        """記錄發(fā)送嘗試"""
        cursor = self.conn.cursor()
        cursor.execute(
            'INSERT INTO send_history (success, message, weather_data) VALUES (?, ?, ?)',
            (success, message, str(weather_data))
        )
        self.conn.commit()
    
    def get_weather_data(self) -> Dict[str, Any]:
        """獲取完整的天氣數(shù)據(jù)"""
        self.logger.info("開始獲取天氣數(shù)據(jù)...")
        
        weather_data = {}
        
        # 獲取當(dāng)前天氣
        current_weather = self.weather_service.get_current_weather()
        if current_weather:
            weather_data.update(current_weather)
        else:
            self.logger.error("獲取當(dāng)前天氣數(shù)據(jù)失敗")
            return {}
        
        # 獲取天氣預(yù)報(bào)
        forecast = self.weather_service.get_daily_forecast(days=3)
        if forecast:
            weather_data['forecast'] = forecast
        else:
            self.logger.warning("獲取天氣預(yù)報(bào)數(shù)據(jù)失敗")
        
        # 獲取天氣預(yù)警
        warnings = self.weather_service.get_weather_warning()
        if warnings:
            weather_data['warnings'] = warnings
        
        self.logger.info("天氣數(shù)據(jù)獲取完成")
        return weather_data
    
    def generate_weather_report(self) -> str:
        """生成完整的天氣報(bào)告"""
        try:
            # 獲取天氣數(shù)據(jù)
            weather_data = self.get_weather_data()
            if not weather_data:
                return "抱歉,今天無法獲取天氣信息。請(qǐng)手動(dòng)查看天氣哦~"
            
            # 生成智能建議
            advice_data = self.weather_analyzer.generate_comprehensive_advice(weather_data)
            
            # 生成個(gè)性化消息
            forecast_data = weather_data.get('forecast', [])
            message = self.message_generator.generate_message(
                weather_data, advice_data, forecast_data
            )
            
            return message
            
        except Exception as e:
            self.logger.error(f"生成天氣報(bào)告時(shí)發(fā)生錯(cuò)誤: {str(e)}")
            return f"今天天氣服務(wù)出了點(diǎn)小問題,但我的關(guān)心不會(huì)變~記得查看天氣哦!"
    
    def send_daily_reminder(self):
        """發(fā)送每日提醒(主函數(shù))"""
        self.logger.info("開始發(fā)送每日天氣提醒...")
        
        try:
            # 生成天氣報(bào)告
            message = self.generate_weather_report()
            
            # 發(fā)送消息
            success = self.message_sender.send_multiple_ways(message, self.config)
            
            # 記錄發(fā)送結(jié)果
            weather_data = self.get_weather_data()  # 重新獲取用于記錄
            self._log_send_attempt(success, message, weather_data)
            
            if success:
                self.logger.info("每日天氣提醒發(fā)送成功")
            else:
                self.logger.error("所有發(fā)送方式均失敗")
                
            return success
            
        except Exception as e:
            self.logger.error(f"發(fā)送每日提醒時(shí)發(fā)生錯(cuò)誤: {str(e)}")
            self._log_send_attempt(False, f"Error: {str(e)}", {})
            return False
    
    def setup_schedule(self):
        """設(shè)置定時(shí)任務(wù)"""
        # 解析發(fā)送時(shí)間
        hour, minute = map(int, self.config['send_time'].split(':'))
        
        # 添加每日定時(shí)任務(wù)
        self.scheduler.add_job(
            self.send_daily_reminder,
            trigger=CronTrigger(hour=hour, minute=minute),
            id='daily_weather_reminder',
            name='每日天氣提醒',
            replace_existing=True
        )
        
        self.logger.info(f"已設(shè)置每日 {hour:02d}:{minute:02d} 發(fā)送天氣提醒")
    
    def send_test_message(self):
        """發(fā)送測試消息"""
        self.logger.info("發(fā)送測試消息...")
        return self.send_daily_reminder()
    
    def start(self):
        """啟動(dòng)系統(tǒng)"""
        try:
            # 設(shè)置定時(shí)任務(wù)
            self.setup_schedule()
            
            # 啟動(dòng)調(diào)度器
            self.scheduler.start()
            
            self.logger.info("天氣提醒系統(tǒng)已啟動(dòng)")
            
            # 立即發(fā)送一次測試消息
            self.send_test_message()
            
            # 保持程序運(yùn)行
            try:
                while True:
                    # 主線程可以在這里執(zhí)行其他任務(wù)
                    # 或者簡單地等待
                    import time
                    time.sleep(60)
            except KeyboardInterrupt:
                self.logger.info("收到中斷信號(hào),正在關(guān)閉系統(tǒng)...")
                
        except Exception as e:
            self.logger.error(f"啟動(dòng)系統(tǒng)時(shí)發(fā)生錯(cuò)誤: {str(e)}")
        finally:
            self.shutdown()
    
    def shutdown(self):
        """關(guān)閉系統(tǒng)"""
        if hasattr(self, 'scheduler') and self.scheduler.running:
            self.scheduler.shutdown()
        
        if hasattr(self, 'conn'):
            self.conn.close()
        
        self.logger.info("天氣提醒系統(tǒng)已關(guān)閉")


def main():
    """主函數(shù)"""
    
    # 可以在這里覆蓋默認(rèn)配置
    custom_config = {
        'city': '上海',  # 修改為女朋友所在城市
        'send_time': '08:00',  # 修改為合適的發(fā)送時(shí)間
        # 添加其他自定義配置...
    }
    
    # 創(chuàng)建并啟動(dòng)系統(tǒng)
    reminder_system = DailyWeatherReminder(custom_config)
    reminder_system.start()


if __name__ == "__main__":
    main()

6. 部署與運(yùn)行

6.1 本地運(yùn)行

創(chuàng)建項(xiàng)目目錄結(jié)構(gòu):

weather_reminder/
├── main.py
├── weather_service.py
├── weather_analyzer.py
├── message_generator.py
├── message_sender.py
├── .env
├── requirements.txt
└── config.json (可選)

安裝依賴:

pip install -r requirements.txt

配置環(huán)境變量(.env文件):

WEATHER_API_KEY=你的和風(fēng)天氣API_KEY
WEATHER_CITY=北京
EMAIL_HOST=smtp.qq.com
EMAIL_PORT=587
EMAIL_USER=你的QQ郵箱
EMAIL_PASSWORD=QQ郵箱授權(quán)碼
RECIPIENT_EMAIL=女朋友的郵箱
RECIPIENT_NAME=親愛的
SEND_TIME=07:30

運(yùn)行系統(tǒng):

python main.py

6.2 服務(wù)器部署

對(duì)于24小時(shí)運(yùn)行,建議部署到云服務(wù)器:

使用systemd服務(wù)(Linux):創(chuàng)建/etc/systemd/system/weather-reminder.service

[Unit]
Description=Daily Weather Reminder
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/path/to/weather_reminder
ExecStart=/usr/bin/python3 main.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

使用Docker部署

創(chuàng)建Dockerfile:

FROM python:3.9-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "main.py"]

6.3 微信版本特別說明

如果要使用微信版本,需要注意:

安裝itchat-uos(解決微信網(wǎng)頁版登錄問題):

pip install itchat-uos

修改代碼使用微信發(fā)送:

# 在message_sender中啟用微信發(fā)送
def send_wechat_message(self, content: str) -> bool:
    import itchat
    
    # 自動(dòng)登錄(會(huì)彈出二維碼)
    itchat.auto_login(hotReload=True, enableCmdQR=2)
    
    # 發(fā)送給文件傳輸助手(測試用)
    itchat.send(content, toUserName='filehelper')
    
    # 或者發(fā)送給指定好友
    friends = itchat.search_friends(name='女朋友的微信昵稱')
    if friends:
        itchat.send(content, toUserName=friends[0]['UserName'])
    
    itchat.logout()
    return True

7. 個(gè)性化定制建議

7.1 添加特殊日期提醒

MessageGenerator類中添加你們的特殊日期:

special_dates = {
    'anniversary': datetime(2024, 5, 20),  # 紀(jì)念日
    'birthday': datetime(2024, 8, 15),     # 生日
    'valentine': datetime(2024, 2, 14),    # 情人節(jié)
    'first_meet': datetime(2024, 3, 8)     # 初次見面日
}

7.2 自定義關(guān)懷語句

豐富問候語和結(jié)束語庫:

self.greetings = [
    "早安,我的小太陽{}!",
    "{}寶貝,新的一天開始啦",
    "嘿,{}!今天也是愛你的一天",
    "早上好,{}!你是我今天第一個(gè)想念的人"
]

self.closing_remarks = [
    "記得按時(shí)吃飯,你胃不好~",
    "今天也要想我一千遍哦",
    "工作再忙也要記得休息,心疼你",
    "晚上視頻哦,想你??"
]

7.3 天氣相關(guān)的情話

根據(jù)天氣添加不同的情話:

def get_weather_pickup_line(self, weather_text: str) -> str:
    """根據(jù)天氣生成情話"""
    lines = {
        '晴': "今天的陽光和你一樣溫暖我的心",
        '雨': "雨水可以打濕街道,但打不濕我想你的心",
        '云': "云朵遮住了太陽,但遮不住我對(duì)你的思念",
        '雪': "雪花飄落的時(shí)候,我在想你有沒有穿暖",
        '風(fēng)': "風(fēng)兒吹過,帶去我對(duì)你的牽掛"
    }
    
    for key, line in lines.items():
        if key in weather_text:
            return line
    return "無論什么天氣,你都是我的晴天"

8. 故障排除與優(yōu)化

8.1 常見問題解決

問題1:API調(diào)用失敗

  • 檢查API Key是否正確
  • 確認(rèn)網(wǎng)絡(luò)連接正常
  • 查看天氣服務(wù)商的服務(wù)狀態(tài)

問題2:郵件發(fā)送失敗

  • 檢查郵箱授權(quán)碼(不是登錄密碼)
  • 確認(rèn)SMTP服務(wù)器地址和端口正確
  • 檢查防火墻設(shè)置

問題3:定時(shí)任務(wù)不執(zhí)行

  • 確認(rèn)系統(tǒng)時(shí)間正確
  • 檢查調(diào)度器是否正常啟動(dòng)
  • 查看日志文件排查錯(cuò)誤

8.2 性能優(yōu)化建議

緩存城市信息:避免重復(fù)查詢城市位置

錯(cuò)誤重試機(jī)制:網(wǎng)絡(luò)請(qǐng)求失敗時(shí)自動(dòng)重試

備用數(shù)據(jù)源:準(zhǔn)備多個(gè)天氣API備用

消息隊(duì)列:使用Redis等管理發(fā)送任務(wù)

8.3 監(jiān)控與維護(hù)

  • 日志監(jiān)控:定期檢查系統(tǒng)日志
  • API使用量:監(jiān)控天氣API調(diào)用次數(shù)
  • 發(fā)送成功率:統(tǒng)計(jì)消息發(fā)送成功率
  • 定期備份:備份配置和發(fā)送記錄

9. 完整代碼文件

由于完整的代碼較長,這里提供各模塊的文件劃分:

9.1 requirements.txt

requests>=2.28.0
apscheduler>=3.9.0
python-dotenv>=0.19.0
python-dateutil>=2.8.0
itchat-uos>=1.5.0

9.2 weather_service.py

(包含WeatherService類,詳見第4.1節(jié))

9.3 weather_analyzer.py

(包含WeatherAnalyzer類,詳見第4.2節(jié))

9.4 message_generator.py

(包含MessageGenerator類,詳見第4.3節(jié))

9.5 message_sender.py

(包含MessageSender類,詳見第4.4節(jié))

9.6 main.py

(包含DailyWeatherReminder主類,詳見第5節(jié))

10. 總結(jié)

通過本文的指導(dǎo),你已經(jīng)學(xué)會(huì)了如何使用Python構(gòu)建一個(gè)功能完整、貼心實(shí)用的每日天氣提醒系統(tǒng)。這個(gè)系統(tǒng)不僅技術(shù)上有價(jià)值,更重要的是它承載了你的情感和關(guān)懷。

10.1 技術(shù)收獲

  • 掌握了API調(diào)用的最佳實(shí)踐
  • 學(xué)會(huì)了構(gòu)建模塊化的Python應(yīng)用
  • 了解了定時(shí)任務(wù)的實(shí)現(xiàn)方式
  • 掌握了異常處理和日志記錄

10.2 情感價(jià)值

這個(gè)天氣提醒系統(tǒng)的真正價(jià)值在于:

  • 持續(xù)關(guān)懷:每天準(zhǔn)時(shí)的提醒體現(xiàn)持續(xù)的關(guān)注
  • 個(gè)性化:根據(jù)天氣提供的建議展現(xiàn)細(xì)心和體貼
  • 實(shí)用性:真實(shí)的天氣信息幫助日常生活
  • 驚喜感:特殊日子的特別提醒增加浪漫氛圍

10.3 擴(kuò)展思路

你可以進(jìn)一步擴(kuò)展這個(gè)系統(tǒng):

  • 添加更多消息平臺(tái)(釘釘、飛書等)
  • 集成日歷系統(tǒng),提醒重要日程
  • 添加機(jī)器學(xué)習(xí),學(xué)習(xí)女朋友的偏好
  • 開發(fā)手機(jī)APP,提供更好的交互體驗(yàn)

記住,技術(shù)只是工具,真正打動(dòng)人心的永遠(yuǎn)是你的用心和關(guān)懷。希望這個(gè)天氣提醒系統(tǒng)能為你們的感情增添一份科技的溫暖!

溫馨提示:在使用過程中,請(qǐng)尊重女朋友的隱私和偏好,確保她喜歡這樣的關(guān)懷方式。技術(shù)應(yīng)該服務(wù)于感情,而不是替代真實(shí)的交流和相處。祝你們的感情像精心編寫的代碼一樣,穩(wěn)定而美好!

以上就是使用Python編寫一個(gè)每日天氣提醒的詳細(xì)內(nèi)容,更多關(guān)于Python每日天氣提醒的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論