feat(data_manager): 增强新闻获取功能,支持指定时间范围查询和历史数据检索

This commit is contained in:
Qihang Zhang 2025-04-20 17:13:06 +08:00
parent 90045379d0
commit cf605ac5b8

View File

@ -201,50 +201,52 @@ class DataFetcher:
DataFetcher.get_news() DataFetcher.get_news()
@staticmethod @staticmethod
def get_news(src='sina', fields=None): def get_news(src='sina', fields=None, start_date=None, end_date=None):
""" """
智能获取新闻数据只获取数据库中不存在的部分 智能获取新闻数据可获取指定时间范围内的数据
参数 参数
src (str): 新闻来源'sina''wallstreetcn' src (str): 新闻来源'sina''wallstreetcn'
fields (str): 需要获取的字段默认为'datetime,title,channels,content' fields (str): 需要获取的字段默认为'datetime,title,channels,content'
start_date (str): 可选的开始日期格式'YYYY-MM-DD HH:MM:SS'
end_date (str): 可选的结束日期格式'YYYY-MM-DD HH:MM:SS'默认为当前时间
返回 返回
bool: 是否成功获取数据 bool: 是否成功获取数据
""" """
table_name = 'news' table_name = 'news'
# 固定的历史起始点 # 固定的历史起始点
HISTORY_START = '2025-04-15 00:00:00' HISTORY_START = '2025-04-01 00:00:00'
# 如果未指定字段,设置默认字段 # 如果未指定字段,设置默认字段
if fields is None: if fields is None:
fields = 'datetime,title,channels,content' fields = 'datetime,title,channels,content'
# 获取当前时间作为结束时间 # 确定结束时间
end_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') if end_date is None:
end_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 检查表是否存在,确定起始时间 # 确定开始时间
if not db_manager.table_exists(table_name): if start_date:
logger.info(f"{table_name} 不存在,将获取从 {HISTORY_START} 至今的所有新闻数据") logger.info(f"使用用户指定的开始日期: {start_date}")
# 从固定起始点获取所有数据 # 如果未指定开始日期,使用智能逻辑确定
elif not db_manager.table_exists(table_name):
logger.info(f"{table_name} 不存在,将获取从 {HISTORY_START}{end_date} 的新闻数据")
start_date = HISTORY_START start_date = HISTORY_START
else: else:
# 表存在,查询最新的新闻时间 # 表存在,查询符合条件的最新的新闻时间
try: try:
newest_query = f"SELECT MAX(datetime) as max_time FROM {table_name}" # 查询小于等于end_date的最新新闻时间
newest_query = f"SELECT MAX(datetime) as max_time FROM {table_name} WHERE datetime <= '{end_date}'"
newest_result = db_manager.query(newest_query) newest_result = db_manager.query(newest_query)
# 如果有数据并且值不为None # 如果有数据并且值不为None
if not newest_result.empty and newest_result['max_time'].iloc[0] is not None: if not newest_result.empty and newest_result['max_time'].iloc[0] is not None:
newest_time = newest_result['max_time'].iloc[0] newest_time = newest_result['max_time'].iloc[0]
logger.info(f"数据库中最新的新闻时间为: {newest_time}") logger.info(f"数据库中小于等于 {end_date} 的最新新闻时间为: {newest_time}")
# 从最新时间开始获取新数据 # 从最新时间开始获取新数据
start_date = newest_time start_date = newest_time
else: else:
# 数据库表存在但没有数据 # 数据库表存在但没有符合条件的数据
logger.info(f"数据库表 {table_name} 存在但没有数据,将获取从 {HISTORY_START} 至今的所有新闻数据") logger.info(
f"数据库表 {table_name} 存在但没有小于等于 {end_date} 的数据,将获取从 {HISTORY_START}{end_date} 的新闻数据")
start_date = HISTORY_START start_date = HISTORY_START
except Exception as e: except Exception as e:
logger.error(f"查询最新新闻时间时出错: {e}") logger.error(f"查询最新新闻时间时出错: {e}")
@ -252,6 +254,14 @@ class DataFetcher:
# 出错时,从固定起始点获取 # 出错时,从固定起始点获取
start_date = HISTORY_START start_date = HISTORY_START
# 检查时间范围有效性
start_datetime = datetime.strptime(start_date, '%Y-%m-%d %H:%M:%S')
end_datetime = datetime.strptime(end_date, '%Y-%m-%d %H:%M:%S')
if start_datetime >= end_datetime:
logger.info(f"开始时间 {start_date} 不早于结束时间 {end_date},无需获取数据")
return True
logger.info(f"开始获取 {start_date}{end_date} 的新闻数据") logger.info(f"开始获取 {start_date}{end_date} 的新闻数据")
return DataFetcher._fetch_news_recursive(src, start_date, end_date, fields, table_name) return DataFetcher._fetch_news_recursive(src, start_date, end_date, fields, table_name)
@ -403,7 +413,7 @@ class DataReader:
return [] return []
@staticmethod @staticmethod
def get_table_data_by_date(table_name, start_date=None, end_date=None, filter_main_board=True): def get_table_data_by_date(table_name, start_date=None, end_date=None, filter_main_board=False):
""" """
从数据库获取指定表的数据并截取指定日期范围内的数据 从数据库获取指定表的数据并截取指定日期范围内的数据
@ -411,7 +421,7 @@ class DataReader:
table_name (str): 数据库表名 table_name (str): 数据库表名
start_date (str): 开始日期格式'YYYYMMDD'默认为30天前 start_date (str): 开始日期格式'YYYYMMDD'默认为30天前
end_date (str): 结束日期格式'YYYYMMDD'默认为今天 end_date (str): 结束日期格式'YYYYMMDD'默认为今天
filter_main_board (bool): 是否只返回主板上市股票的数据默认为True filter_main_board (bool): 是否只返回主板上市股票的数据默认为False
error_prefix (str): 错误日志的前缀 error_prefix (str): 错误日志的前缀
返回 返回
@ -453,3 +463,33 @@ class DataReader:
logger.error(f"获取{table_name}数据时出错: {e}") logger.error(f"获取{table_name}数据时出错: {e}")
logger.debug(f"完整的错误追踪信息:\n{traceback.format_exc()}") logger.debug(f"完整的错误追踪信息:\n{traceback.format_exc()}")
return pd.DataFrame() return pd.DataFrame()
@staticmethod
def get_news(start_date=None, end_date=None, update=False):
# 先检查表是否存在
if not db_manager.table_exists('news') or update:
logger.debug(f"表 trade_cal 不存在")
# 自动拉取交易日历
try:
DataFetcher.get_news()
except Exception as e:
logger.error(f"自动拉去news时出错: {e}")
logger.debug(f"完整的错误追踪信息:\n{traceback.format_exc()}")
return []
# 设置默认日期范围
if start_date is None:
start_date = '2025-04-15 00:00:00'
if end_date is None:
end_date = datetime.now().strftime('YYYY-MM-DD HH:MM:SS')
try:
# 查询数据
df = db_manager.load_df_from_db('news', conditions=f"datetime BETWEEN '{start_date}' AND '{end_date}'")
return df
except Exception as e:
logger.error(f"获取news数据时出错: {e}")
logger.debug(f"完整的错误追踪信息:\n{traceback.format_exc()}")
return pd.DataFrame()