Files
xwlb/newsRedo.py
T
simon 60f8c263f2 《新闻联播》每日抓取入库:全链路 + 可移植化 + 定时任务
从 CCTV 主页抓取《新闻联播》,下载 → 转 MP3/WAV → 静音切分 → ASR 识别
→ LLM 校对 → 切分为单条新闻 → 入库 MySQL。

主要内容:
- 全链路:getVideo5 抓取下载、audioRead 转写、deepseek 校对与切分、newsProcess 入库
- 可移植化:配置分层,.env 只放密钥、config.yml 放模型/接入点/路由/参数
- 可换供应商:endpoints(kind/base_url/api_key_env/extra_body)+ routes 按环节选路
- 数据保真:数值事实守卫,校对改动数字/年份/届次则整片回退 ASR 原文;
  识别不完整不发布该日精编,避免半天内容被当成完整一天
- 定时任务:systemd 每天 21:00,失败 21:30 / 22:00 重试;
  只缺切分时只重跑切分(省掉全部 ASR),用 state/.asr_complete_* 标记判定阶段
- 隧道自愈:13306 不通时自动执行 autossh.sh(所有入口共用,systemd 托管时只等待)
- 中间产物每日清理;97 项离线自检(配置/清理/事实守卫/解析/隧道)
2026-09-25 11:17:46 +08:00

123 lines
4.1 KiB
Python

"""
newsRedo — 手动重新执行新闻 AI 分割流程。
用法:
python newsRedo.py # 默认当天日期
python newsRedo.py 20250601 # yyyymmdd 格式
python newsRedo.py 2025-06-01 # yyyy-mm-dd 格式
python newsRedo.py 2025-06-01 --force # 已有精编记录也重新切分
流程:
1. 检查 xwlb_daily_ext 是否已有记录 → 已处理过则跳过(--force 可强制重跑)
2. 检查 xwlb_daily 是否有当天记录 → 无记录则先跑 getVideo5 全流程
3. 有记录但未处理 → 直接执行 news_to_db() AI 分割
"""
import sys
import re
import logging
from datetime import datetime
from mysqlHandle import MySQLDB
from newsProcess import news_to_db
from getVideo5 import process_videos
import config
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def _parse_date(date_str):
"""解析日期,返回 (yyyymmdd_str, yyyy_mm_dd_str),或报错退出"""
if not date_str:
today = datetime.now()
d8 = today.strftime('%Y%m%d')
d10 = today.strftime('%Y-%m-%d')
logger.info(f"未指定日期,使用当天: {d10}")
return d8, d10
if re.match(r'^\d{4}-\d{2}-\d{2}$', date_str):
try:
datetime.strptime(date_str, '%Y-%m-%d')
except ValueError:
print(f"无效日期: {date_str}")
sys.exit(1)
return date_str.replace('-', ''), date_str
if re.match(r'^\d{8}$', date_str):
try:
datetime.strptime(date_str, '%Y%m%d')
except ValueError:
print(f"无效日期: {date_str}")
sys.exit(1)
return date_str, f"{date_str[:4]}-{date_str[4:6]}-{date_str[6:8]}"
print("日期格式错误,请使用 yyyymmdd 或 yyyy-mm-dd 格式")
sys.exit(1)
def main():
args = [a for a in sys.argv[1:] if not a.startswith('-')]
force = '--force' in sys.argv[1:] or '-f' in sys.argv[1:]
date_str = args[0] if args else None
date_d8, date_d10 = _parse_date(date_str)
db = MySQLDB()
# 1. 检查 xwlb_daily_ext 是否已处理过
# 判据由「>5 条」改为「存在任意记录」(原判据会把只切出 ≤5 条的日期永久判为未处理,B13)
try:
ext_count = db.query_data(
table="xwlb_daily_ext",
columns="COUNT(*) as count",
where="news_date = %s",
params=(date_d10,)
)
existing = ext_count[0]['count'] if ext_count else 0
if existing > 0 and not force:
logger.info(f"日期 {date_d10} 已有 {existing} 条精编记录,无需重新处理(需重跑请加 --force)。")
return
if existing > 0 and force:
logger.info(f"日期 {date_d10} 已有 {existing} 条精编记录,--force 将重新切分并覆盖。")
except Exception as e:
logger.error(f"查询 xwlb_daily_ext 失败: {e}")
finally:
db.close()
db = MySQLDB()
# 2. 检查 xwlb_daily 是否有当天数据
try:
daily_count = db.query_data(
table="xwlb_daily",
columns="COUNT(*) as count",
where="news_days = %s",
params=(date_d10,)
)
has_daily = daily_count and daily_count[0]['count'] > 0
except Exception as e:
logger.error(f"查询 xwlb_daily 失败: {e}")
has_daily = False
finally:
db.close()
# 3. 分支处理
if has_daily:
logger.info(f"日期 {date_d10} 在 xwlb_daily 中有记录,直接执行 AI 分割。")
try:
status = news_to_db(date_d10, force=force)
logger.info(f"news_to_db 结果: {status}")
except Exception as e:
logger.error(f"news_to_db 执行出错: {e}")
sys.exit(1)
else:
logger.info(f"日期 {date_d10} 在 xwlb_daily 中无记录,重新执行视频下载全流程。")
try:
process_videos(date_d8, date_d8)
except Exception as e:
logger.error(f"process_videos 执行出错: {e}")
sys.exit(1)
if __name__ == "__main__":
config.log_summary()
main()