feat: 日报结构化入库(M10 前后端分离数据层)
- 新增 report_db 包: MySQL 连接/建表/幂等写入 (news_report/news_event, myquant 库) - 新增 report_import 包: 历史 178 份日报 HTML 解析入库, 表头驱动列映射 - reporter.py 完全切换: generate_report 结构化入库, 不再生成/上传 HTML - CLI: 新增 report-import 子命令 - 依赖: uv add pymysql; 配置: NEWS_DB_* / REPORT_HISTORY_DIR - 文档: docs/report_db_design.md(实现逻辑), docs/db_schema.md(表结构供 API/前端) - 测试: 24 个单测通过 (parser/builder/models/importer)
This commit is contained in:
+27
-8
@@ -18,6 +18,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import Counter
|
||||
@@ -394,24 +395,34 @@ def cmd_status(args: argparse.Namespace) -> int: # noqa: ARG001
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
def cmd_report(args: argparse.Namespace) -> int:
|
||||
"""生成 HTML 日报并上传到 Web 服务器。"""
|
||||
"""生成日报并结构化入库(M10:不再生成 HTML/上传)。"""
|
||||
load_dotenv()
|
||||
from scheduler.reporter import generate_report
|
||||
|
||||
day_str = args.date or _today()
|
||||
print(f"📊 生成日报: {day_str}")
|
||||
path = generate_report(day_str, upload=not args.no_upload)
|
||||
if path is None:
|
||||
report_id = generate_report(day_str, upload=not args.no_upload)
|
||||
if report_id is None:
|
||||
print("⚠️ 无数据或生成失败")
|
||||
return 1
|
||||
print(f"✅ 日报已保存: {path}")
|
||||
if not args.no_upload:
|
||||
from datetime import date as dt_date
|
||||
today_str = dt_date.today().strftime("%Y%m%d")
|
||||
print(f"✅ 已上传: http://doorcome.cn/echart/research/{today_str}/")
|
||||
print(f"✅ 日报已入库: report_id={report_id}")
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_report_import(args: argparse.Namespace) -> int:
|
||||
"""历史日报 HTML 解析入库(M10)。"""
|
||||
load_dotenv()
|
||||
from report_import.importer import import_history
|
||||
|
||||
report_dir = args.dir or os.environ.get("REPORT_HISTORY_DIR", "data/reports_history")
|
||||
print(f"📥 导入历史日报: {report_dir} (date={args.date or '全部'} type={args.type or '全部'})")
|
||||
stats = import_history(report_dir, date_str=args.date, report_type=args.type, force=args.force)
|
||||
print(f"✅ 扫描 {stats.scanned} | 新导入 {stats.imported} | 跳过 {stats.skipped} | 失败 {stats.failed}")
|
||||
for err in stats.errors[:20]:
|
||||
print(f" ❌ {err}")
|
||||
return 0 if stats.failed == 0 else 1
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# discover — 自动分析站点,生成 sources.yaml 配置建议
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -917,6 +928,14 @@ def main() -> int:
|
||||
pl = sp.add_parser("list", help="查看关注列表")
|
||||
pl.set_defaults(func=cmd_watchlist_list)
|
||||
|
||||
# ---- report-import ----
|
||||
p = sub.add_parser("report-import", help="历史日报 HTML 解析入库 (M10)")
|
||||
p.add_argument("--dir", default=None, help="日报目录(默认 REPORT_HISTORY_DIR)")
|
||||
p.add_argument("--date", default=None, help="仅导入指定日期 YYYYMMDD")
|
||||
p.add_argument("--type", default=None, choices=["finance", "intl"], help="仅导入指定类型")
|
||||
p.add_argument("--force", action="store_true", help="已存在也覆盖重导")
|
||||
p.set_defaults(func=cmd_report_import)
|
||||
|
||||
# ---- stock-report ----
|
||||
p = sub.add_parser("stock-report", help="生成关注列表个股日报")
|
||||
p.add_argument("--no-upload", action="store_true", help="仅生成不上传")
|
||||
|
||||
Reference in New Issue
Block a user