#!/bin/bash # update.sh - 自动从 Google Sheet 拉取 EG Nagwa 当月数据并生成 data.json # 数据源:公开导出的 Google Sheet CSV # 每天由服务器自动执行一次(见 schedule.conf) set -euo pipefail SHEET_ID="11Npr4IpXT8jtgUnrkrjITJ8s1fHNYTwRRwSGIvcfeIs" GID="699511110" CSV_URL="https://docs.google.com/spreadsheets/d/${SHEET_ID}/export?format=csv&gid=${GID}" OUT="data.json" TMP_CSV="$(mktemp)" trap 'rm -f "$TMP_CSV"' EXIT # 当月,格式如 September-2026 MONTH_TAG="$(date +%B-%Y)" echo "Fetching CSV for month: $MONTH_TAG" curl -fsSL "$CSV_URL" -o "$TMP_CSV" # 用 python 解析 CSV 生成 data.json(python3 处理带引号/逗号的字段更稳妥) python3 - "$TMP_CSV" "$OUT" "$MONTH_TAG" <<'PY' import csv, json, sys, re from datetime import datetime csv_path, out_path, month_tag = sys.argv[1], sys.argv[2], sys.argv[3] def num(s): if s is None: return None s = s.strip().replace(',', '').replace('$', '').replace('%', '') if s == '': return None try: f = float(s) return int(f) if f.is_integer() else f except ValueError: return None rows = list(csv.reader(open(csv_path, newline='', encoding='utf-8'))) # 列索引(0-based),依据表头布局: # Month=7, DT=8, Geo=9, Install=10, Price=11, MidasSpend=12, # PayableSpend=13, Enroll_Session=14, Enroll_Session%=15, Remark=16, # meta-key=17, meta-value=18 COL_MONTH, COL_DT, COL_INSTALL = 7, 8, 10 COL_PAYABLE, COL_ENROLL, COL_ENROLLPCT = 13, 14, 15 COL_METAK, COL_METAV = 16, 17 daily = [] meta = {"geo": "EG", "product": "Nagwa"} # 从 month_tag 解析目标年月,用于把 DT(如 2026/9/1 或 20260901)标准化成 YYYY-MM-DD target_month = datetime.strptime(month_tag, "%B-%Y") ty, tm = target_month.year, target_month.month def parse_dt(dt): dt = dt.strip() if not dt: return None # 形如 2026/9/1 m = re.match(r'^(\d{4})/(\d{1,2})/(\d{1,2})$', dt) if m: y, mo, d = map(int, m.groups()) return f"{y:04d}-{mo:02d}-{d:02d}" # 形如 20260901 m = re.match(r'^(\d{4})(\d{2})(\d{2})$', dt) if m: y, mo, d = map(int, m.groups()) return f"{y:04d}-{mo:02d}-{d:02d}" return None price_seen = None for r in rows: if len(r) <= COL_ENROLLPCT: continue if r[COL_MONTH].strip() != month_tag: continue date = parse_dt(r[COL_DT]) if not date: continue install = num(r[COL_INSTALL]) or 0 spend = num(r[COL_PAYABLE]) or 0.0 enroll = num(r[COL_ENROLL]) or 0 pct = num(r[COL_ENROLLPCT]) or 0.0 daily.append({ "date": date, "install": int(install), "payable_spend": round(float(spend), 2), "enroll_session": int(enroll), "enroll_session_pct": round(float(pct), 2), }) # 记录价格(取当月出现的最新价) p = num(r[11]) if p is not None: price_seen = p # 抓取 meta(Remark 区块的 key/value) k = r[COL_METAK].strip() if len(r) > COL_METAK else "" v = r[COL_METAV].strip() if len(r) > COL_METAV else "" if k and v: kl = k.lower() if "budget" in kl: meta["sep_budget"] = num(v) elif kl == "spend": meta["spend"] = num(v) elif kl == "left": meta["left"] = num(v) elif kl == "%": meta["spend_pct"] = v if v.endswith('%') else (v + '%') elif "daily install" in kl: meta["rec_daily_install"] = num(v) if price_seen is not None: meta["price"] = price_seen data = {"meta": meta, "daily": daily} with open(out_path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"Wrote {len(daily)} days to {out_path}") PY echo "Done. Last run: $(date)"