diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a15d0c --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# 定时任务 + +## 天气任务 +### API接口 +  接口地址:[和风天气](https://dev.qweather.com/) + +### 使用说明 +1. 登录和风天气控制台,点击设置,查看专属API Host。 +2. 点击项目管理,新建项目,并添加凭据(本项目采用API KEY方式)。 +3. 查看[接口文档](https://dev.qweather.com/docs/start/),编写业务逻辑。 + +## 股票任务 +### API接口 +  接口地址:东方财富网:http://push2.eastmoney.com/api/qt/stock/get + +## 企业微信消息推送 +### 接口文档 +  [消息推送](https://developer.work.weixin.qq.com/document/path/99110) + +### 使用说明 +1. 在企业微信群创建消息推送。 +2. 查看WebHook地址。 +3. 根据文档编写业务逻辑。 \ No newline at end of file diff --git a/log_config.py b/config/log_config.py similarity index 100% rename from log_config.py rename to config/log_config.py diff --git a/main.py b/main.py index 74580b4..7650076 100644 --- a/main.py +++ b/main.py @@ -1,36 +1,28 @@ import schedule import time -from log_config import logger +from config.log_config import logger -from daily_stock import get_stock_message, get_today_stock -from daily_weather import get_today_indices, get_today_weather, get_weather_message -from wechat_message import send_wechat_message +from work.daily_stock import get_stock_message, get_today_stock +from work.daily_weather import get_today_indices, get_today_weather, get_weather_message +from message.wechat_message import send_wechat_message, MessageEnum def daily_weather_task(): logger.info("执行定时天气任务...") weather = get_today_weather() indices = get_today_indices() - message = get_weather_message(weather, indices) - send_wechat_message(message) + send_wechat_message(MessageEnum.MARKDOWN2, get_weather_message(weather, indices), True) def daily_stock_task(): logger.info("执行定时股票任务...") stock = get_today_stock() - message = get_stock_message(stock) - send_wechat_message(message) + send_wechat_message(MessageEnum.MARKDOWN, get_stock_message(stock)) def daily_order_supper_task(): logger.info("执行定时订饭任务...") - message = { - "msgtype": "text", - "text": { - "content": "📢 订饭时间到!记得订晚饭~" - } - } - send_wechat_message(message) + send_wechat_message(MessageEnum.TEXT, "📢 订饭时间到!记得订晚饭~") def setup_schedule(): @@ -48,9 +40,9 @@ def run_schedule(): def main(): logger.info("程序启动,开始设置定时任务...") - #daily_weather_task() - #daily_stock_task() - #daily_order_supper_task() + # daily_weather_task() + # daily_stock_task() + # daily_order_supper_task() setup_schedule() try: @@ -62,5 +54,6 @@ def main(): except Exception as e: logger.error(f"程序发生错误: {str(e)}", exc_info=True) + if __name__ == "__main__": main() diff --git a/message/wechat_message.py b/message/wechat_message.py new file mode 100644 index 0000000..02dd898 --- /dev/null +++ b/message/wechat_message.py @@ -0,0 +1,40 @@ +from enum import Enum + +import requests +import json + +webhook_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send' +webhook_key_estun = 'f09eb098-f709-4fc6-83b5-4a08a8431b8f' +webhook_key_sweet_hut = '5ccae111-43a1-4672-a94f-0d34713259c0' + + +class MessageEnum(Enum): + TEXT = 'text' + MARKDOWN = 'markdown' + MARKDOWN2 = 'markdown2' + + +def send_wechat_message(message_type: MessageEnum, message: str, has_sweet_hut=False): + wechat_message = {} + match message_type: + case MessageEnum.TEXT: + wechat_message = {"msgtype": "text", "text": {"content": message}} + case MessageEnum.MARKDOWN: + wechat_message = {"msgtype": "markdown", "markdown": {"content": message}} + case MessageEnum.MARKDOWN2: + wechat_message = {"msgtype": "markdown_v2", "markdown_v2": {"content": message}} + + requests.post( + webhook_url, + headers={"Content-Type": "application/json"}, + params={'key': webhook_key_estun}, + data=json.dumps(wechat_message, ensure_ascii=False).encode('utf-8') + ) + + if has_sweet_hut: + requests.post( + webhook_url, + headers={"Content-Type": "application/json"}, + params={'key': webhook_key_sweet_hut}, + data=json.dumps(wechat_message, ensure_ascii=False).encode('utf-8') + ) diff --git a/wechat_message.py b/wechat_message.py deleted file mode 100644 index c6fe32e..0000000 --- a/wechat_message.py +++ /dev/null @@ -1,18 +0,0 @@ -import requests -import json - -webhook_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send' -webhook_key = 'f09eb098-f709-4fc6-83b5-4a08a8431b8f' - - -def send_wechat_message(message): - response = requests.post( - webhook_url, - headers={ - "Content-Type": "application/json" - }, - params={'key': webhook_key}, - data=json.dumps(message, ensure_ascii=False).encode('utf-8') - ) - - return response.json() diff --git a/daily_stock.py b/work/daily_stock.py similarity index 67% rename from daily_stock.py rename to work/daily_stock.py index 10e7a00..723d65e 100644 --- a/daily_stock.py +++ b/work/daily_stock.py @@ -13,7 +13,7 @@ def get_today_stock(company_id=estun_id): return response.json() -def get_stock_message(stock): +def get_stock_message(stock) -> str: # 获取真实数据 current_price = stock['data']['f43'] / 100 prev_close = stock['data']['f60'] / 100 @@ -25,9 +25,4 @@ def get_stock_message(stock): # 根据涨跌确定颜色 color = "warning" if change_percent < 0 else "info" - return { - "msgtype": "markdown", - "markdown": { - "content": f"📈 **埃斯顿(002747)**\n> 现价: {current_price}元\n> 涨跌: {change_percent_rounded}%" - } - } + return f"📈 **埃斯顿(002747)**\n> 现价: {current_price}元\n> 涨跌: {change_percent_rounded}%" diff --git a/daily_weather.py b/work/daily_weather.py similarity index 67% rename from daily_weather.py rename to work/daily_weather.py index f65b529..2b4be48 100644 --- a/daily_weather.py +++ b/work/daily_weather.py @@ -1,17 +1,16 @@ import requests from datetime import datetime -weather_url = 'https://p478kygkjw.re.qweatherapi.com/' +weather_url = 'https://p478kygkjw.re.qweatherapi.com' weather_api_key = '4aa47f183c694aaa812ff018be8270e4' nanjing_location = '101190101' def get_today_weather(city_location=nanjing_location): + url = f'{weather_url}/v7/weather/3d' response = requests.get( - f'{weather_url}v7/weather/3d', - headers={ - 'X-QW-Api-Key': f'{weather_api_key}' - }, + url=url, + headers={'X-QW-Api-Key': f'{weather_api_key}'}, params={'location': city_location} ) @@ -19,21 +18,17 @@ def get_today_weather(city_location=nanjing_location): def get_today_indices(city_location=nanjing_location): + url = f'{weather_url}/v7/indices/1d' response = requests.get( - f'{weather_url}v7/indices/1d', - headers={ - 'X-QW-Api-Key': f'{weather_api_key}' - }, - params={ - 'location': city_location, - 'type': '0' - } + url=url, + headers={'X-QW-Api-Key': f'{weather_api_key}'}, + params={'location': city_location, 'type': '0'} ) return response.json() -def get_weather_message(weather, indices): +def get_weather_message(weather, indices) -> str: textDay = weather['daily'][0]['textDay'] textNight = weather['daily'][0]['textNight'] weather_desc = textDay if textDay == textNight else f"{textDay}转{textNight}" @@ -62,7 +57,7 @@ def get_weather_message(weather, indices): } # 构建markdown内容 - markdown_content = f"""# 🌤️ 今日天气播报 + return f"""# 🌤️ 今日天气播报 ## 📍 基本信息 **城市:** {weather_data["city"]} **日期:** {weather_data["date"]} @@ -75,19 +70,17 @@ def get_weather_message(weather, indices): - **风力:** {weather_data["wind"]} ## 📊 生活指数 -| 指数类型 | 等级 | 建议 | -|---------|-----|------| -| 😊 舒适度指数 | {weather_data["life_index"][0]["level"]} | {weather_data["life_index"][0]["advice"]} | -| 👕 穿衣指数 | {weather_data["life_index"][1]["level"]} | {weather_data["life_index"][1]["advice"]} | -| 🏃 运动指数 | {weather_data["life_index"][2]["level"]} | {weather_data["life_index"][2]["advice"]} | -| 🚗 洗车指数 | {weather_data["life_index"][3]["level"]} | {weather_data["life_index"][3]["advice"]} | +😊 **舒适度指数:** {weather_data["life_index"][0]["level"]} + 建议:{weather_data["life_index"][0]["advice"]} + +👕 **穿衣指数:** {weather_data["life_index"][1]["level"]} + 建议:{weather_data["life_index"][1]["advice"]} + +🏃 **运动指数:** {weather_data["life_index"][2]["level"]} + 建议:{weather_data["life_index"][2]["advice"]} + +🚗 **洗车指数:** {weather_data["life_index"][3]["level"]} + 建议:{weather_data["life_index"][3]["advice"]} --- *数据来源:{weather_data['data_source']}*""" - - return { - "msgtype": "markdown_v2", - "markdown_v2": { - "content": markdown_content - } - }