优化记录_super_vault_20260817.md 6.0 KB

super_vault 采集 优化记录

日期:2026/08/17 涉及文件:super_vault_daily_spider.py 关联表:super_vault_product_record

1. 优化背景

最近几天(2026/08/13–08/15)入库的数据,completion_time(完成时间)和 sold_time(售罄成交时刻)两个时间字段大量为空(NULL)。需要定位成因并判断能否补齐。

诊断结论(两个字段成因不同)

通过按 status 分布统计 + 逐个实测 /app/teamup/detail 接口,得到两条清晰规律:

completion_time:平台只在团走到 status=9(发货完成)时才生成。

  • 库中 747 条 status=9 的团全部有值status=8/0/10/3 等未完成态源头即为 None(detail 接口实测全部返回 None)。
  • 截图中的团为 status=8(待发货),尚未走到完成态,平台自身还未生成 completionTime。属正常业务状态,当前无法补齐,等团发货完成、status 变 9 后由日常任务自动带上。

sold_time:平台只在团「售罄」后才生成,且存在历史遗留缺口。

库中状态 detail 现在有 soldTime 能否补 原因
status=8 待发货(已满员售罄) 能补 列表首次入库后才售罄,旧值未回写
status=3 已推进到售罄的 部分有 能补 同上
status=9 早期完成团(约 570 条) 补不了 平台早期无 soldTime 字段,源头即空
status=0 预售未开卖 无(soldCount=0) 不需补 尚未售出
status=10 未售罄结束 无(soldCount<count) 补不了 未售罄,源头无值

根因:列表接口首次入库走 INSERT IGNORE(只增不改),团在入库后才售罄,soldTime 由平台事后生成,旧值不再回写;本应由 update_stale_products 每日刷新补齐,但常驻进程 start_cxx_spider.py(每天 07:01 跑 daily 任务)近两天未运行,导致漏补。

2. 改动内容

super_vault_daily_spider.py 中:

  1. 新增轻量专职函数 backfill_sold_time(log, sql_pool, token)

    • 候选范围:sold_time IS NULL AND sold_count > 0 AND status IN (3, 8)(已售罄/售后阶段、大概率能拿到 soldTime 的团)。
    • 逐个查 /detail仅当返回 soldTime 时才 UPDATE,且只写 sold_time 单字段,源头无值即跳过,不误写。
    • 复用现有带重试的 get_teamup_detail();每次请求 sleep(0.3) 限速。
  2. 挂进 cxx_daily_main:在 get_vod_list(拉列表)之后、update_stale_products 之前调用,使最新入库的团优先补上 sold_time

为什么单独做而不复用 update_stale_products:后者是「全字段重刷」的重任务(候选上千、耗时十几分钟,且会每日白查约 570 个源头无 soldTime 的历史团)。把 sold_time 这一高频刚需拎成轻量步骤(仅扫几十个团、只改单字段),更快、职责单一,即使将来重任务被调整/降频,sold_time 仍有专职兜底。

3. 改动前后对比

新增函数

def backfill_sold_time(log, sql_pool, token):
    """精准补齐已售罄团缺失的 sold_time(售罄成交时刻)。"""
    rows = sql_pool.select_all(
        "SELECT pid FROM super_vault_product_record "
        "WHERE sold_time IS NULL AND sold_count > 0 AND status IN (3, 8)")
    pids = [r[0] for r in rows] if rows else []
    log.info(f"待补 sold_time 的已售罄团 {len(pids)} 个")
    filled = 0
    for pid in pids:
        try:
            data = get_teamup_detail(log, pid, token)
            if not data:
                continue
            sold_time = data.get("soldTime")
            if not sold_time:          # 源头也无(团未真正售罄),跳过不误写
                continue
            sql_pool.update_one_or_dict(
                table="super_vault_product_record",
                data={"sold_time": sold_time},
                condition={"pid": pid})
            filled += 1
        except Exception as e:
            log.error(f"补 sold_time pid={pid} 失败: {e}")
        time.sleep(0.3)                # 限速,避免请求过密触发风控
    log.info(f"sold_time 补齐完成,成功回写 {filled}/{len(pids)} 个")

主流程接入(cxx_daily_main)

        # 获取所有 pid
        try:
            get_vod_list(log, sql_pool, token[0])
        except Exception as e:
            log.error(f"Error fetching last_product_id: {e}")

        # 精准补齐已售罄团(status 3/8)的 sold_time:轻量、只改单字段,最新入库的团先补上
        try:
            backfill_sold_time(log, sql_pool, token[0])
        except Exception as e:
            log.error(f"Error backfilling sold_time: {e}")

        # 刷新未完成拼团(status!=9)的会变字段 ...
        try:
            update_stale_products(log, sql_pool, token[0])
        except Exception as e:
            log.error(f"Error updating stale products: {e}")

一次性手动补数结果

对已售罄团执行精准补数:候选 28 个,补齐 23 条(含截图框住的 pid 2825–2837 等),5 条源头无值跳过。8/15 的 16 条 sold_time 已全部补齐。

4. 注意事项

  1. 必须保证常驻进程运行:新步骤与原有 update_stale_products 都依赖 start_cxx_spider.py(每天 07:01 触发 daily)。最近漏补的真正根因就是该进程未运行——重启后每日任务才会自动补 sold_time
  2. completion_time 当前无法补齐属正常:需等团 status 变为 9(发货完成),平台才生成该字段,届时 update_stale_products 会自动推进 status 并带上完成时间,无需人工干预。
  3. 仍会有少量 sold_time 空且补不了status=9 早期完成团(约 570 条)源头本就无 soldTimestatus=0/10 未售罄团同理。这些非采集遗漏,无需处理。
  4. update_stale_products 存在轻微重叠status=3/8 团在两处都会查一次 detail,每日多约 28 次请求、耗时数秒,可忽略;换来 sold_time 的独立可靠保障。