fetch_daily_hourly_cpm.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #!/usr/bin/env python
  2. """Fetch one day's overall hourly CPM for real-time ad control."""
  3. from __future__ import annotations
  4. import argparse
  5. import re
  6. from datetime import datetime
  7. from pathlib import Path
  8. from zoneinfo import ZoneInfo
  9. from dotenv import load_dotenv
  10. from odps_source import build_odps_client, fetch_hourly_cpm
  11. SHANGHAI = ZoneInfo("Asia/Shanghai")
  12. ROOT = Path(__file__).resolve().parent
  13. def parse_args() -> argparse.Namespace:
  14. parser = argparse.ArgumentParser(description=__doc__)
  15. parser.add_argument(
  16. "--date",
  17. default=datetime.now(SHANGHAI).strftime("%Y%m%d"),
  18. help="Data date in YYYYMMDD format; defaults to today in Asia/Shanghai.",
  19. )
  20. parser.add_argument(
  21. "--output",
  22. type=Path,
  23. help="CSV output path; defaults to outputs/hourly_cpm_<date>.csv.",
  24. )
  25. return parser.parse_args()
  26. def main() -> None:
  27. args = parse_args()
  28. if not re.fullmatch(r"\d{8}", args.date):
  29. raise ValueError("--date must use YYYYMMDD format")
  30. load_dotenv(ROOT.parent / "auto_put_ad_mini" / ".env", override=False)
  31. load_dotenv(Path.cwd() / ".env", override=False)
  32. frame = fetch_hourly_cpm(build_odps_client(), args.date)
  33. if frame.empty:
  34. print(f"No hourly CPM data found for {args.date}.")
  35. return
  36. output_path = args.output or ROOT / "outputs" / f"hourly_cpm_{args.date}.csv"
  37. output_path.parent.mkdir(parents=True, exist_ok=True)
  38. frame.to_csv(output_path, index=False)
  39. display = frame.copy()
  40. display["hour"] = display["hour_of_day"].map(lambda value: f"{value:02d}:00")
  41. display["cpm"] = display["cpm"].map(lambda value: f"{value:.2f}")
  42. print(display[["hour", "impressions", "cpm"]].to_string(index=False))
  43. print(f"hours={len(frame)} latest_partition={frame.iloc[-1]['dt']}")
  44. print(f"output={output_path}")
  45. if __name__ == "__main__":
  46. main()