# -*- coding: utf-8 -*- """ CMS-한정 콘텐츠탭 일괄 검증(읽기전용). _tab_scan_cms.scan() 을 미검수 시군에 돌려 사이트별 탭그룹/예상추가행 리포트 생성. 수정 일절 안 함. 리포트: _temp/_tab_rescan_report.{md,json} """ import sys, os, json, glob, traceback sys.stdout.reconfigure(encoding='utf-8') sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from _tab_scan_cms import scan BASE = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '광역_사이트맵')) REGIONS = ['충청남도', '충청북도', '전북특별자치도', '제주특별자치도'] # 검수완료(손대지 않음) + 서천(이미 전개됨) 제외 SKIP = {'계룡', '공주', '금산', '논산', '보령', '당진', '부여', # 충남 검수완료 '고창', '군산', '김제', '남원', '무주', # 전북 검수완료 '서천'} # 이미 전개 def org_of(path): return os.path.basename(os.path.dirname(path)).split('.', 1)[-1] # "13.청양군" -> "청양군" def main_xlsx(d): cands = [f for f in glob.glob(os.path.join(d, '*.xlsx')) if '_backup_' not in f and not os.path.basename(f).startswith('~$')] return cands[0] if cands else None def discover(): out = [] for region in REGIONS: for d in sorted(glob.glob(os.path.join(BASE, region, '*'))): if not os.path.isdir(d): continue org = os.path.basename(d).split('.', 1)[-1] if any(s in org for s in SKIP): continue x = main_xlsx(d) if x: out.append((org, x)) return out if __name__ == '__main__': targets = discover() print(f"대상 {len(targets)}곳:", ', '.join(o for o, _ in targets)) results = [] for i, (org, x) in enumerate(targets, 1): print(f"\n[{i}/{len(targets)}] {org} ...", flush=True) try: r = scan(x) r['org'] = org results.append(r) print(f" rows={r['rows']} pages={r['pages']} " f"page_tab_groups={r['page_tab_groups']} est_new=+{r['est_new']} " f"inpage={r['inpage_groups']}", flush=True) except Exception as e: print(f" ERROR: {e}", flush=True) traceback.print_exc() results.append({'org': org, 'xlsx': os.path.basename(x), 'error': str(e)}) tdir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '_temp')) os.makedirs(tdir, exist_ok=True) with open(os.path.join(tdir, '_tab_rescan_report.json'), 'w', encoding='utf-8') as f: json.dump(results, f, ensure_ascii=False, indent=1) # 마크다운 리포트 lines = ['# CMS-한정 콘텐츠탭 재스캔 리포트(읽기전용)', '', '> `_tab_scan_cms.scan()` 결과. est_new=시트에 없는 탭링크(펼치기 시 추가될 행 추정).', '> 숫자는 후보 신호이며 펼치기 전 개별 검토 필요.', '', '| 기관 | 행수 | 탭그룹 | 예상+행 | 인페이지탭 | 상태 |', '|---|---|---|---|---|---|'] def stat(r): if 'error' in r: return '⚠️ ERROR' if r['page_tab_groups'] == 0 and r['inpage_groups'] == 0: return '탭없음(확정0)' return '🔴 탭있음(전개대상)' for r in sorted(results, key=lambda r: -(r.get('est_new', 0))): if 'error' in r: lines.append(f"| {r['org']} | - | - | - | - | ⚠️ {r['error'][:30]} |") else: lines.append(f"| {r['org']} | {r['rows']} | {r['page_tab_groups']} | " f"+{r['est_new']} | {r['inpage_groups']} | {stat(r)} |") lines += ['', '## 상위 그룹 상세', ''] for r in sorted(results, key=lambda r: -(r.get('est_new', 0))): if r.get('est_new', 0) == 0: continue lines.append(f"### {r['org']} (dom={r['dom']}, +{r['est_new']}행 / {r['page_tab_groups']}그룹)") for g in r.get('top', []): lines.append(f"- R{g['r']} **{str(g['F'])[:18]}** cls=`{g['cls'][:22]}` " f"tabs={g['tabs']} missing={g['missing']} ex={g['ex']}") lines.append('') with open(os.path.join(tdir, '_tab_rescan_report.md'), 'w', encoding='utf-8') as f: f.write('\n'.join(lines)) print(f"\n리포트 저장: {tdir}\\_tab_rescan_report.md / .json")