98 lines
2.8 KiB
Python
98 lines
2.8 KiB
Python
|
|
"""
|
|||
|
|
新闻总结生成模块
|
|||
|
|
使用规则引擎生成中文总结(不调用外部 AI API)
|
|||
|
|
"""
|
|||
|
|
import logging
|
|||
|
|
from datetime import datetime, timedelta
|
|||
|
|
from collections import defaultdict
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def generate_summary(news_list: list, period: str = "全天") -> str:
|
|||
|
|
"""
|
|||
|
|
生成新闻总结
|
|||
|
|
period: "最近1小时" / "上午" / "全天" / "昨晚到今早"
|
|||
|
|
"""
|
|||
|
|
if not news_list:
|
|||
|
|
return f"📭 {period}暂无重要新闻"
|
|||
|
|
|
|||
|
|
# 按评分排序,高分在前
|
|||
|
|
sorted_news = sorted(news_list, key=lambda x: x.get("score", 0), reverse=True)
|
|||
|
|
|
|||
|
|
# 按来源分组统计
|
|||
|
|
source_count = defaultdict(int)
|
|||
|
|
for n in sorted_news:
|
|||
|
|
source_count[n.get("source_name", "未知")] += 1
|
|||
|
|
|
|||
|
|
# 构建总结
|
|||
|
|
lines = []
|
|||
|
|
lines.append(f"📊 *{period}新闻总结*")
|
|||
|
|
lines.append(f"━━━━━━━━━━━━━━━")
|
|||
|
|
lines.append(f"📰 共 {len(sorted_news)} 条快讯")
|
|||
|
|
lines.append("")
|
|||
|
|
|
|||
|
|
# 🔴 重磅新闻(评分 >= 8)
|
|||
|
|
hot_news = [n for n in sorted_news if n.get("score", 0) >= 8]
|
|||
|
|
if hot_news:
|
|||
|
|
lines.append("🔴 *重磅快讯*")
|
|||
|
|
for n in hot_news[:5]:
|
|||
|
|
emoji = _score_emoji(n.get("score", 0))
|
|||
|
|
lines.append(f" {emoji} {n['title']}")
|
|||
|
|
lines.append("")
|
|||
|
|
|
|||
|
|
# 🟡 值得关注(评分 6-7)
|
|||
|
|
mid_news = [n for n in sorted_news if 6 <= n.get("score", 0) <= 7]
|
|||
|
|
if mid_news:
|
|||
|
|
lines.append("🟡 *值得关注*")
|
|||
|
|
for n in mid_news[:8]:
|
|||
|
|
lines.append(f" • {n['title']}")
|
|||
|
|
lines.append("")
|
|||
|
|
|
|||
|
|
# 来源统计
|
|||
|
|
lines.append("📡 *来源分布*")
|
|||
|
|
for src, cnt in sorted(source_count.items(), key=lambda x: x[1], reverse=True):
|
|||
|
|
lines.append(f" {src}: {cnt}条")
|
|||
|
|
|
|||
|
|
lines.append("")
|
|||
|
|
lines.append(f"⏰ 生成时间: {datetime.now().strftime('%H:%M')}")
|
|||
|
|
|
|||
|
|
return "\n".join(lines)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _score_emoji(score: int) -> str:
|
|||
|
|
"""根据评分返回 emoji"""
|
|||
|
|
if score >= 9:
|
|||
|
|
return "🔥"
|
|||
|
|
elif score >= 8:
|
|||
|
|
return "⚡"
|
|||
|
|
elif score >= 7:
|
|||
|
|
return "📌"
|
|||
|
|
elif score >= 6:
|
|||
|
|
return "📎"
|
|||
|
|
else:
|
|||
|
|
return "•"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_period_range(period: str) -> tuple:
|
|||
|
|
"""
|
|||
|
|
根据时间段名称返回 (start_ts, end_ts)
|
|||
|
|
"""
|
|||
|
|
now = datetime.now()
|
|||
|
|
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
|||
|
|
|
|||
|
|
if period == "最近1小时":
|
|||
|
|
start = now - timedelta(hours=1)
|
|||
|
|
elif period == "上午":
|
|||
|
|
start = today_start.replace(hour=6)
|
|||
|
|
now = min(now, today_start.replace(hour=12))
|
|||
|
|
elif period == "全天":
|
|||
|
|
start = today_start
|
|||
|
|
elif period == "昨晚到今早":
|
|||
|
|
start = (today_start - timedelta(days=1)).replace(hour=20)
|
|||
|
|
now = today_start.replace(hour=8)
|
|||
|
|
else:
|
|||
|
|
start = now - timedelta(hours=3)
|
|||
|
|
|
|||
|
|
return int(start.timestamp()), int(now.timestamp())
|