# -*- coding: utf-8 -*- """전기안전공사 LNB(.sub_left_menu) 4단 권위트리 재추출 → _gnb\1.json. 대분류(GNB d1) > 섹션(LNB d0=E) > 항목(d1=F) > 세부(d2=G).""" import sys, io, os, json, re sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') from playwright.sync_api import sync_playwright GNB = r"D:\01.프로젝트\DB수집\작업파일\공공기관2\_gnb\1.json" old = json.load(open(GNB, encoding='utf-8')) # 대분류(depth1) 목록 majors = [(r['label'], r['href']) for r in old['gnb'] if r['depth'] == 1] LNB_JS = """ () => { const lnb = document.querySelector('.sub_left_menu, #snb, .snb, .lnb'); if(!lnb) return {rows:[]}; const rows=[]; lnb.querySelectorAll('a').forEach(a=>{ let d=0,p=a.parentElement; while(p&&p!==lnb){ if(p.tagName==='UL')d++; p=p.parentElement; } let label=(a.textContent||'').trim().replace(/\\s+/g,' '); label=label.replace(/하위메뉴(닫기|열기)$/,'').trim(); let href=a.getAttribute('href')||''; if(href==='#'||href.startsWith('javascript')) href=''; else if(href && !href.startsWith('http')) href='https://www.kesco.or.kr'+ (href.startsWith('/')?href:'/'+href); if(label) rows.push({d, label, href}); }); return {rows}; } """ def clean(label): return label out_rows = [] with sync_playwright() as p: br = p.chromium.launch(headless=True) pg = br.new_context(ignore_https_errors=True, viewport={'width':1600,'height':1000}).new_page() for name, href in majors: try: pg.goto(href, wait_until='domcontentloaded', timeout=30000) pg.wait_for_timeout(1800) r = pg.evaluate(LNB_JS) except Exception as e: print(f"[{name}] 실패 {e}"); out_rows.append({'depth':1,'label':name,'href':href}); continue lnb = r['rows'] # 대분류 행 out_rows.append({'depth':1, 'label':name, 'href':href}) # LNB d0->depth2, d1->depth3, d2->depth4 ... for n in lnb: out_rows.append({'depth': 2 + n['d'], 'label': n['label'], 'href': n['href']}) d1cnt = sum(1 for n in lnb if n['d']==0) print(f"[{name}] LNB {len(lnb)}항목 (섹션 {d1cnt})") br.close() old['gnb'] = out_rows old['base'] = 'https://www.kesco.or.kr' json.dump(old, open(GNB, 'w', encoding='utf-8'), ensure_ascii=False, indent=1) print('총', len(out_rows), '행 →', GNB)