Spaces:
Running
Running
| """ | |
| Step 12: 현업 키워드 Excel → real_menus.json 업데이트 | |
| 엑셀 파일(현업분류 시트)에서 키워드(현업) + 키워드(채널기획)를 | |
| SCREEN_NUM 기준으로 union/중복제거 후 real_menus.json keywords 필드 갱신. | |
| 실행: | |
| python scripts/12_update_keywords.py | |
| python scripts/12_update_keywords.py --input "경로/파일.xlsx" | |
| 출력: | |
| data/raw/real_menus.json (keywords 업데이트) | |
| data/updated_menu_ids.json (변경된 menu_id 목록 → 13번 스크립트에서 사용) | |
| """ | |
| import argparse | |
| import json | |
| import re | |
| from pathlib import Path | |
| import pandas as pd | |
| SCRIPT_DIR = Path(__file__).parent | |
| ROOT = SCRIPT_DIR.parent | |
| EXCEL_DEFAULT = Path(r"C:\Users\leeju\Documents\s#ai메뉴\Keyword_images\화면별 키워드 기재_요청안_최종.xlsx") | |
| REAL_MENUS_PATH = ROOT / "data" / "raw" / "real_menus.json" | |
| UPDATED_IDS_PATH = ROOT / "data" / "updated_menu_ids.json" | |
| def parse_keywords(cell_value: str) -> list: | |
| """쉼표·공백 구분 키워드 파싱 → 공백 제거 + 빈 문자열 제거""" | |
| if not cell_value or (isinstance(cell_value, float)): | |
| return [] | |
| # 쉼표 혹은 줄바꿈으로 분리 | |
| parts = re.split(r"[,\n]", str(cell_value)) | |
| return [p.strip() for p in parts if p.strip()] | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--input", default=str(EXCEL_DEFAULT), help="엑셀 파일 경로") | |
| args = parser.parse_args() | |
| excel_path = Path(args.input) | |
| if not excel_path.exists(): | |
| print(f"[오류] 엑셀 파일 없음: {excel_path}") | |
| return | |
| # ── 1. 엑셀 현업분류 시트 읽기 ────────────────────────────────────── | |
| print(f"[1/4] 엑셀 읽기: {excel_path.name}") | |
| df = pd.read_excel(excel_path, sheet_name="현업분류", dtype=str, engine="openpyxl") | |
| biz_col = "키워드 (현업)" | |
| ch_col = "키워드 (채널기획)" | |
| # SCREEN_NUM → union 키워드 딕셔너리 | |
| screen_keywords: dict[str, list] = {} | |
| for _, row in df.iterrows(): | |
| snum = str(row.get("SCREEN_NUM", "")).strip() | |
| if not snum: | |
| continue | |
| kw_biz = parse_keywords(row.get(biz_col, "")) | |
| kw_ch = parse_keywords(row.get(ch_col, "")) | |
| # union: 현업 우선, 채널기획 추가 (중복 제거, 순서 보존) | |
| seen = set() | |
| merged = [] | |
| for kw in kw_biz + kw_ch: | |
| if kw not in seen: | |
| seen.add(kw) | |
| merged.append(kw) | |
| if merged: | |
| screen_keywords[snum] = merged | |
| print(f" 키워드 있는 SCREEN_NUM: {len(screen_keywords)}개") | |
| # ── 2. real_menus.json 읽기 ────────────────────────────────────────── | |
| print("[2/4] real_menus.json 읽기") | |
| menus = json.loads(REAL_MENUS_PATH.read_text(encoding="utf-8")) | |
| screen_to_menu = {str(m["screen_num"]): m for m in menus} | |
| # ── 3. keywords 업데이트 ────────────────────────────────────────────── | |
| print("[3/4] keywords 업데이트") | |
| updated_ids = [] | |
| no_match = [] | |
| for snum, new_kws in screen_keywords.items(): | |
| menu = screen_to_menu.get(snum) | |
| if menu is None: | |
| no_match.append(snum) | |
| continue | |
| old_kws = menu.get("keywords", []) | |
| if set(old_kws) != set(new_kws): | |
| menu["keywords"] = new_kws | |
| updated_ids.append(menu["menu_id"]) | |
| print(f" 업데이트: {len(updated_ids)}개 메뉴") | |
| print(f" 매칭 안된 SCREEN_NUM: {len(no_match)}개") | |
| if no_match[:5]: | |
| print(f" (샘플): {no_match[:5]}") | |
| # ── 4. 저장 ──────────────────────────────────────────────────────────── | |
| print("[4/4] 저장") | |
| REAL_MENUS_PATH.write_text( | |
| json.dumps(menus, ensure_ascii=False, indent=2), | |
| encoding="utf-8" | |
| ) | |
| UPDATED_IDS_PATH.parent.mkdir(parents=True, exist_ok=True) | |
| UPDATED_IDS_PATH.write_text( | |
| json.dumps(updated_ids, ensure_ascii=False, indent=2), | |
| encoding="utf-8" | |
| ) | |
| print(f"[완료] real_menus.json 갱신 ({len(updated_ids)}개)") | |
| print(f"[완료] updated_menu_ids.json 저장 → {UPDATED_IDS_PATH}") | |
| if __name__ == "__main__": | |
| main() | |