#!/usr/bin/env python3 """CoolBotDataSys 每日飞书日报推送""" import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import requests import logging from datetime import datetime from database import db logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def get_collection_stats(): """获取藏品统计""" with db.get_cursor() as cursor: cursor.execute("SELECT COUNT(*) as cnt FROM collections") total = cursor.fetchone()["cnt"] return {"total_collections": total} def get_yichens_stats(): """获取一尘数据统计""" with db.get_cursor() as cursor: # 总帖子数 cursor.execute("SELECT COUNT(*) as cnt FROM yichens_posts") total_posts = cursor.fetchone()["cnt"] # 今日新增 cursor.execute("SELECT COUNT(*) as cnt FROM yichens_posts WHERE DATE(crawled_at) = CURDATE()") today_posts = cursor.fetchone()["cnt"] # 交易帖数量 cursor.execute("SELECT COUNT(*) as cnt FROM yichens_posts WHERE post_type = 'deal'") deal_posts = cursor.fetchone()["cnt"] # 有价格标注的帖子 cursor.execute("SELECT COUNT(*) as cnt FROM yichens_posts WHERE price IS NOT NULL AND price > 0") priced_posts = cursor.fetchone()["cnt"] # 今日价格区间统计 cursor.execute(""" SELECT COUNT(*) as cnt, AVG(price) as avg_price, MIN(price) as min_price, MAX(price) as max_price FROM yichens_posts WHERE price IS NOT NULL AND price > 0 AND DATE(crawled_at) = CURDATE() """) today_price_stats = cursor.fetchone() # 最新帖子(标题示例) cursor.execute(""" SELECT title, price, price_unit FROM yichens_posts WHERE price IS NOT NULL AND price > 0 ORDER BY crawled_at DESC LIMIT 5 """) latest_with_price = cursor.fetchall() # 最近爬虫状态 cursor.execute(""" SELECT source, status, items_count, finished_at FROM crawl_logs ORDER BY finished_at DESC LIMIT 3 """) crawl_status = cursor.fetchall() return { "total_posts": total_posts, "today_posts": today_posts, "deal_posts": deal_posts, "priced_posts": priced_posts, "today_price_stats": today_price_stats, "latest_with_price": latest_with_price, "crawl_status": crawl_status } def build_feishu_message(collection_stats, yichens_stats): """构建飞书消息卡片""" now = datetime.now() # 最新价格帖子示例 latest_items = "" for item in yichens_stats.get("latest_with_price", []): price_str = f"¥{item['price']}{item['price_unit']}" if item['price'] else "价格待确认" latest_items += f"- {item['title'][:30]}... : {price_str}\n" if not latest_items: latest_items = "今日暂无价格数据\n" # 爬虫状态 crawl_info = "" for log in yichens_stats.get("crawl_status", []): status_emoji = "✅" if log["status"] == "success" else "❌" crawl_info += f"{status_emoji} {log['source']}: {log['items_count']}条 @ {log['finished_at']}\n" if not crawl_info: crawl_info = "暂无爬虫运行记录\n" # 价格统计 price_stats = yichens_stats.get("today_price_stats", {}) price_info = "" if price_stats and price_stats.get("cnt", 0) > 0: price_info = f"均价: ¥{price_stats['avg_price']:.0f} | 区间: ¥{price_stats['min_price']:.0f}~¥{price_stats['max_price']:.0f} ({price_stats['cnt']}条)" else: price_info = "今日暂无价格统计" message = { "msg_type": "interactive", "card": { "header": { "title": {"tag": "plain_text", "content": f"📊 CoolBotDataSys 日报 {now.strftime('%Y-%m-%d %H:%M')}"}, "template": "blue" }, "elements": [ { "tag": "div", "text": { "tag": "lark_md", "content": ( f"**🐉 一尘连体纪念钞数据**\n" f"- 总帖子: {yichens_stats['total_posts']} 条\n" f"- 今日新增: +{yichens_stats['today_posts']} 条\n" f"- 交易帖: {yichens_stats['deal_posts']} 条\n" f"- 有价格: {yichens_stats['priced_posts']} 条\n\n" f"**💰 今日价格动态**\n{price_info}\n\n" f"**📈 最新交易帖**\n{latest_items}\n\n" f"**🔄 爬虫状态**\n{crawl_info}" ) } }, {"tag": "hr"}, { "tag": "note", "elements": [ {"tag": "plain_text", "content": f"CoolBotDataSys · {now.strftime('%H:%M:%S')}"} ] } ] } } return message def send_feishu(message): """发送飞书消息""" webhook = os.environ.get("FEISHU_WEBHOOK_URL", "") if not webhook: logger.warning("飞书Webhook未配置,跳过发送") return False try: response = requests.post(webhook, json=message, timeout=10) result = response.json() if result.get("code") == 0 or result.get("StatusCode") == 0: logger.info("✅ 飞书消息发送成功") return True else: logger.error(f"❌ 飞书发送失败: {result}") return False except Exception as e: logger.error(f"❌ 飞书发送异常: {e}") return False def main(): logger.info("📊 开始生成日报...") collection_stats = get_collection_stats() yichens_stats = get_yichens_stats() print(f"统计概览:") print(f" 一尘帖子总数: {yichens_stats['total_posts']}") print(f" 今日新增: {yichens_stats['today_posts']}") print(f" 交易帖: {yichens_stats['deal_posts']}") print(f" 有价格标注: {yichens_stats['priced_posts']}") message = build_feishu_message(collection_stats, yichens_stats) print(f"\n消息卡片内容预览:") print(message["card"]["elements"][0]["text"]["content"][:500]) # 检查是否启用飞书推送 webhook = os.environ.get("FEISHU_WEBHOOK_URL", "") if webhook: send_feishu(message) else: print("\n⚠️ 未配置 FEISHU_WEBHOOK_URL 环境变量,跳过飞书推送") return yichens_stats if __name__ == "__main__": main()