# -*- coding: utf-8 -*- from playwright.sync_api import sync_playwright import json BASE='https://www.kipf.re.kr' def clean(h): if not h: return '' h=h.split(';jsessionid')[0] if h.startswith('http'): return h if h.startswith('/'): return BASE+h return h with sync_playwright() as p: b=p.chromium.launch();pg=b.new_page(ignore_https_errors=True) pg.goto('https://www.kipf.re.kr/kor/',timeout=40000,wait_until='domcontentloaded') pg.wait_for_selector('a.th_1st',timeout=20000) pg.wait_for_timeout(1500) tree=pg.evaluate(r'''()=>{ function txt(a){return (a.innerText||a.textContent||'').trim().replace(/\s+/g,' ');} const tops=[]; document.querySelectorAll('a.th_1st').forEach(a=>{ const li=a.closest('li'); const node={t:txt(a), h:a.getAttribute('href'), mids:[]}; li.querySelectorAll('ul.depth2_ul>li').forEach(ml=>{ const ma=ml.querySelector(':scope>a'); const m={t:ma?txt(ma):'?', h:ma?ma.getAttribute('href'):'', leaves:[]}; ml.querySelectorAll(':scope>ul.depth3_ul>li>a').forEach(la=>{ m.leaves.push({t:txt(la), h:la.getAttribute('href')}); }); node.mids.push(m); }); tops.push(node); }); return tops; }''') b.close() for t in tree: t['h']=clean(t['h']) for m in t['mids']: m['h']=clean(m['h']) for l in m['leaves']: l['h']=clean(l['h']) json.dump(tree,open('_gnb_tree.json','w',encoding='utf-8'),ensure_ascii=False,indent=1) # summary tot=0 for t in tree: leafcnt=sum(len(m['leaves']) or 1 for m in t['mids']) tot+=leafcnt print(f"TOP {t['t']} | mids={len(t['mids'])} | rows~{leafcnt}") for m in t['mids']: print(f" E {m['t']} ({len(m['leaves'])}F) {m['h']}") print('총 예상 행 ~',tot)