Support monthly source rollover; update data - 8/29-8/31
The 2609 file carries only 8/31 and has no 投手 sheet, so build_data.py now globs every *每日数据-武汉萌奇熊.xlsx, merges 平台消耗统计 per date (newer filename wins for a repeated date), and takes the roster from the newest file that still has a 投手 sheet. Future month rollovers need no code change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+36
-16
@@ -5,10 +5,14 @@
|
||||
# 规则:@某某 == 某某;未填投放人的 Adpingid 丢弃;
|
||||
# exclude.json 的 packages(按包名)与 adpings(按 Adpingid)永久剔除,均为精确匹配。
|
||||
# 每个 package 明细:Geo 后缀 = 该 package 花费最高的地区;Adpingid = 该地区内花费最高的 Adping。
|
||||
import openpyxl, collections, json, datetime, os, sys
|
||||
import openpyxl, collections, json, datetime, os, sys, glob
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
SRC = os.path.join(HERE, '2608每日数据-武汉萌奇熊.xlsx')
|
||||
# 源文件按月滚动(2608 -> 2609 -> ...)。全部读进来合并:
|
||||
# 同一天出现在多个文件时,以文件名较新的为准(源表会修订历史数据)。
|
||||
SRC_FILES = sorted(glob.glob(os.path.join(HERE, '*每日数据-武汉萌奇熊.xlsx')))
|
||||
if not SRC_FILES:
|
||||
sys.exit('ERROR: 仓库里找不到 *每日数据-武汉萌奇熊.xlsx')
|
||||
_cfg = json.load(open(os.path.join(HERE, 'exclude.json')))
|
||||
EXCL = set(_cfg['packages']) # 按包名剔除
|
||||
EXCL_ADP = set(_cfg.get('adpings', {})) # 按 Adpingid 剔除
|
||||
@@ -20,12 +24,20 @@ def key(v):
|
||||
return str(int(v))
|
||||
return str(v).strip()
|
||||
|
||||
wb = openpyxl.load_workbook(SRC, data_only=True)
|
||||
books = [(f, openpyxl.load_workbook(f, data_only=True)) for f in SRC_FILES]
|
||||
|
||||
# --- 投手表:取最新一个带「投手」sheet 的文件(月度文件可能不含该表)---
|
||||
roster_file, roster = None, None
|
||||
for f, wb_ in reversed(books):
|
||||
if '投手' in wb_.sheetnames:
|
||||
roster_file, roster = f, wb_['投手']
|
||||
break
|
||||
if roster is None:
|
||||
sys.exit('ERROR: 所有源文件都没有「投手」sheet,无法归属投放人')
|
||||
|
||||
# --- 投手表:Adpingid -> 投放人 ---
|
||||
amap = {}
|
||||
dropped_ids = set(EXCL_ADP) # 先纳入按 Adpingid 剔除的,再补上按包名命中的
|
||||
for r in wb['投手'].iter_rows(min_row=2, values_only=True):
|
||||
for r in roster.iter_rows(min_row=2, values_only=True):
|
||||
adp, pkg, buyer, status = r[1], r[3], r[11], r[0]
|
||||
if adp is None or str(status).strip() == '示例':
|
||||
continue
|
||||
@@ -42,19 +54,25 @@ for r in wb['投手'].iter_rows(min_row=2, values_only=True):
|
||||
|
||||
owned = collections.Counter(amap.values()) # 每位投手名下的 Adpingid 数(已扣除排除包名)
|
||||
|
||||
# --- 平台消耗统计 ---
|
||||
rows = []
|
||||
for r in wb['平台消耗统计'].iter_rows(min_row=2, values_only=True):
|
||||
d, adp, pkg, geo, spend = r[1], r[2], r[3], r[4], r[8]
|
||||
if d is None or adp is None or not isinstance(d, datetime.datetime):
|
||||
# --- 平台消耗统计:逐文件读取,按日期归组,新文件覆盖同一天的旧数据 ---
|
||||
by_date = {}
|
||||
for f, wb_ in books:
|
||||
if '平台消耗统计' not in wb_.sheetnames:
|
||||
continue
|
||||
try:
|
||||
s = float(spend) if spend is not None else 0.0
|
||||
except (TypeError, ValueError):
|
||||
s = 0.0
|
||||
rows.append((d.date(), key(adp), (str(pkg).strip() if pkg else '(未知)'),
|
||||
(str(geo).strip() if geo else ''), s))
|
||||
day = collections.defaultdict(list)
|
||||
for r in wb_['平台消耗统计'].iter_rows(min_row=2, values_only=True):
|
||||
d, adp, pkg, geo, spend = r[1], r[2], r[3], r[4], r[8]
|
||||
if d is None or adp is None or not isinstance(d, datetime.datetime):
|
||||
continue
|
||||
try:
|
||||
s = float(spend) if spend is not None else 0.0
|
||||
except (TypeError, ValueError):
|
||||
s = 0.0
|
||||
day[d.date()].append((d.date(), key(adp), (str(pkg).strip() if pkg else '(未知)'),
|
||||
(str(geo).strip() if geo else ''), s))
|
||||
by_date.update(day) # books 已按文件名升序,后者覆盖前者
|
||||
|
||||
rows = [r for day_rows in by_date.values() for r in day_rows]
|
||||
if not rows:
|
||||
sys.exit('ERROR: 平台消耗统计 无有效数据行')
|
||||
|
||||
@@ -132,6 +150,8 @@ data = {
|
||||
}
|
||||
json.dump(data, open(os.path.join(HERE, 'data.json'), 'w'), ensure_ascii=False, indent=2)
|
||||
|
||||
print('源文件:', ', '.join(os.path.basename(f) for f in SRC_FILES))
|
||||
print('投手表取自:', os.path.basename(roster_file))
|
||||
print(f"窗口 {start} -> {end}")
|
||||
print(f"排除包名命中 {excluded_rows} 行,剔除花费 {excluded_spend:.2f}")
|
||||
print(f"合计 {data['grand_total']:.2f} / Adpingid {data['week34_id_count']}")
|
||||
|
||||
Reference in New Issue
Block a user