Files
teamai-global/skills/daily-hot-news/storage.py
T
NightStar 3d3dd79df0 Add 39 shared skills from local agent inventory
Sources: ~/.openclaw/skills, ~/.agents/skills, workshop-skills, workspace/skills
2026-09-10 16:54:57 +08:00

346 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
每日热榜 Skill - 数据存储模块
功能:
- 自动保存每日热榜数据
- 查询历史热榜记录
- 管理数据文件
"""
import json
import os
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any
from config import config
class DataStorage:
"""数据存储类"""
def __init__(self):
self.data_dir = config.data_dir
self.auto_save = config.auto_save
os.makedirs(self.data_dir, exist_ok=True)
def save_hot_list(self, source_id: str, data: Dict[str, Any]) -> bool:
"""
保存热榜数据到文件
Args:
source_id: 热榜源 ID(如 weibo, zhihu)
data: 热榜数据字典
Returns:
是否保存成功
"""
if not self.auto_save:
return False
try:
# 获取今日日期的文件路径
file_path = config.get_data_path(source_id)
# 构建存储结构
storage_data = {
"source_id": source_id,
"save_time": datetime.now().isoformat(),
"update_time": data.get("update_time", ""),
"total": data.get("total", 0),
"data": data.get("data", [])
}
# 读取现有数据(如果有)
existing_data = []
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
try:
existing_data = json.load(f)
if not isinstance(existing_data, list):
existing_data = []
except:
existing_data = []
# 添加新数据到列表
existing_data.append(storage_data)
# 保存到文件
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(existing_data, f, ensure_ascii=False, indent=2)
return True
except Exception as e:
print(f"[DataStorage] 保存失败: {e}")
return False
def load_history(self, source_id: str = "", days: int = 7) -> Dict[str, List[Dict]]:
"""
加载历史热榜数据
Args:
source_id: 热榜源 ID(空则加载所有源)
days: 加载最近几天的数据
Returns:
按日期组织的热榜数据
"""
result = {}
if source_id:
# 加载指定源的历史数据
source_dir = os.path.join(self.data_dir, source_id)
if not os.path.exists(source_dir):
return {}
for i in range(days):
date_str = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
file_path = os.path.join(source_dir, f"{date_str}.json")
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
try:
data = json.load(f)
result[date_str] = data
except:
continue
else:
# 加载所有源的历史数据
if not os.path.exists(self.data_dir):
return {}
for source in os.listdir(self.data_dir):
source_dir = os.path.join(self.data_dir, source)
if not os.path.isdir(source_dir):
continue
result[source] = {}
for i in range(days):
date_str = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
file_path = os.path.join(source_dir, f"{date_str}.json")
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
try:
data = json.load(f)
result[source][date_str] = data
except:
continue
return result
def get_saved_dates(self, source_id: str) -> List[str]:
"""
获取指定热榜源已保存的日期列表
Args:
source_id: 热榜源 ID
Returns:
已保存的日期列表(降序)
"""
dates = []
source_dir = os.path.join(self.data_dir, source_id)
if not os.path.exists(source_dir):
return []
for filename in os.listdir(source_dir):
if filename.endswith('.json'):
date_str = filename.replace('.json', '')
dates.append(date_str)
return sorted(dates, reverse=True)
def get_old_data_files(self, days: int = 7) -> List[Dict[str, str]]:
"""
获取指定天数之前的旧数据文件列表
Args:
days: 天数阈值(默认7天)
Returns:
旧文件列表 [{source_id, date_str, file_path}]
"""
from datetime import datetime, timedelta
old_files = []
cutoff_date = datetime.now() - timedelta(days=days)
if not os.path.exists(self.data_dir):
return []
for source in os.listdir(self.data_dir):
source_dir = os.path.join(self.data_dir, source)
if not os.path.isdir(source_dir):
continue
for filename in os.listdir(source_dir):
if not filename.endswith('.json'):
continue
try:
file_date = datetime.strptime(filename.replace('.json', ''), "%Y-%m-%d")
if file_date < cutoff_date:
old_files.append({
"source_id": source,
"date_str": filename.replace('.json', ''),
"file_path": os.path.join(source_dir, filename)
})
except:
continue
return old_files
def cleanup_old_files(self, files: List[Dict[str, str]]) -> int:
"""
删除指定的旧文件
Args:
files: 旧文件列表
Returns:
删除的文件数量
"""
deleted_count = 0
for f in files:
try:
if os.path.exists(f["file_path"]):
os.remove(f["file_path"])
deleted_count += 1
except Exception as e:
print(f"[DataStorage] 删除失败 {f['file_path']}: {e}")
return deleted_count
def load_hot_list(self, source_id: str, date_str: str = "") -> Optional[List[Dict]]:
"""
加载指定日期的热榜数据
Args:
source_id: 热榜源 ID
date_str: 日期(默认今天)
Returns:
热榜数据列表
"""
if not date_str:
date_str = datetime.now().strftime("%Y-%m-%d")
file_path = config.get_data_path(source_id, date_str)
if not os.path.exists(file_path):
return None
with open(file_path, 'r', encoding='utf-8') as f:
try:
data = json.load(f)
# 返回当天的最后一条记录
if isinstance(data, list) and len(data) > 0:
return data[-1].get("data", [])
except:
pass
return None
def list_all_data(self) -> Dict[str, int]:
"""
列出所有已保存的热榜数据统计
Returns:
源ID -> 保存记录数
"""
stats = {}
if not os.path.exists(self.data_dir):
return {}
for source in os.listdir(self.data_dir):
source_dir = os.path.join(self.data_dir, source)
if not os.path.isdir(source_dir):
continue
count = 0
for filename in os.listdir(source_dir):
if filename.endswith('.json'):
count += 1
if count > 0:
stats[source] = count
return stats
def clear_old_data(self, keep_days: int = 30) -> int:
"""
清理旧数据
Args:
keep_days: 保留最近几天的数据
Returns:
删除的文件数量
"""
deleted_count = 0
cutoff_date = datetime.now() - timedelta(days=keep_days)
if not os.path.exists(self.data_dir):
return 0
for source in os.listdir(self.data_dir):
source_dir = os.path.join(self.data_dir, source)
if not os.path.isdir(source_dir):
continue
for filename in os.listdir(source_dir):
if not filename.endswith('.json'):
continue
try:
file_date = datetime.strptime(filename.replace('.json', ''), "%Y-%m-%d")
if file_date < cutoff_date:
file_path = os.path.join(source_dir, filename)
os.remove(file_path)
deleted_count += 1
except:
continue
return deleted_count
# 全局存储实例
storage = DataStorage()
def auto_save_hot_list(source_id: str, data: Dict[str, Any]) -> bool:
"""
自动保存热榜数据的便捷函数
在获取热榜数据后调用此函数保存数据
"""
return storage.save_hot_list(source_id, data)
if __name__ == "__main__":
# 测试存储功能
print("📊 每日热榜数据存储管理")
print("=" * 50)
# 列出所有数据
stats = storage.list_all_data()
if stats:
print("\n已保存的热榜数据:")
for source, count in stats.items():
print(f" • {source}: {count} 条记录")
else:
print("\n暂无保存的数据")
# 列出已保存的日期
print("\n已保存的日期(微博):")
dates = storage.get_saved_dates("weibo")
if dates:
for date in dates[:7]:
print(f" • {date}")
else:
print(" 暂无数据")