783dfd059d
智能推荐 / 销量最高两 tab 的离线库此前只有北京(ETL 写死 cityId),改为遍历 美团官方城市字典 359 个地级市全量抓取。实测一个地级市 cityId 已覆盖其下辖县级市 (徐州→邳州/新沂/睢宁等),按地级市抓即可,无需区县层级。 - 城市字典:tools/gen_meituan_cities.py 从美团 Excel 生成随仓库 JSON (app/integrations/data/meituan_cities.json,359 城),app/integrations/cities.py 读取; - ETL:city_id 参数化 + 城市级并发(默认 12)+ worker 启动错峰削平瞬时峰值 + 主线程逐城串行入库(Session 不跨线程); - 配速实测:单城全量 ~110s/~2300 条;15 并发抓完一轮 ~50-60min,402 占 3% 退避全消化; 每 3h 一轮全量(--interval 10800),窗口充裕; - prune 双护栏:本轮 0 入库 或 失败城占比 >5% 时跳过,防上游故障/大面积限流误删全表; - 仅写入侧;读取侧(rec/top-sales 按城过滤)待后续(依赖用户定位→cityId 映射,字典无经纬度)。 --------- Co-authored-by: chenshuobo <1119780489@qq.com> Reviewed-on: #57 Co-authored-by: chenshuobo <chenshuobo@wonderable.ai> Co-committed-by: chenshuobo <chenshuobo@wonderable.ai>
35 lines
1.2 KiB
Python
35 lines
1.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""美团城市字典(地级市)读取。
|
|
|
|
数据源:app/integrations/data/meituan_cities.json,由 tools/gen_meituan_cities.py 从
|
|
美团官方「城市字典」Excel 生成(359 个地级市:city_id / 城市名 / 省份)。
|
|
实测一个地级市 cityId 已覆盖其下辖县级市供给(徐州 → 邳州 / 新沂 / 睢宁 …),故无区县层级。
|
|
|
|
- ETL(scripts/pull_meituan_coupons.py)遍历 all_cities() 全量抓取入库。
|
|
- 读取侧将来「按城市过滤」时,也从这里取 city_id ↔ 城市名映射。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import functools
|
|
import json
|
|
from pathlib import Path
|
|
|
|
_JSON = Path(__file__).resolve().parent / "data" / "meituan_cities.json"
|
|
|
|
|
|
@functools.lru_cache(maxsize=1)
|
|
def all_cities() -> list[dict]:
|
|
"""全部城市 [{city_id, name, province}, ...](359 个地级市)。"""
|
|
return json.loads(_JSON.read_text(encoding="utf-8"))
|
|
|
|
|
|
@functools.lru_cache(maxsize=1)
|
|
def _by_id() -> dict[str, dict]:
|
|
return {c["city_id"]: c for c in all_cities()}
|
|
|
|
|
|
def city_name(city_id: str) -> str | None:
|
|
"""city_id → 城市名(查不到返回 None)。"""
|
|
c = _by_id().get(city_id)
|
|
return c["name"] if c else None
|