# -*- coding: utf-8 -*- """komipo GNB megamenu 권위트리 추출 → _komipo_tree.json (D,E,F,mnCd,type,url)""" import json, re from playwright.sync_api import sync_playwright UA='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36' BASE='https://www.komipo.co.kr' with sync_playwright() as p: b=p.chromium.launch(); pg=b.new_page(user_agent=UA,viewport={'width':1600,'height':2400}) pg.goto('https://www.komipo.co.kr/fr/realName/main.do?mnCd=FN011101',timeout=40000,wait_until='domcontentloaded'); pg.wait_for_timeout(3000) rows=pg.evaluate(r"""()=>{ const nav=document.querySelector('nav'); const out=[]; for(const li1 of nav.querySelectorAll(':scope > ul > li')){ const D=(li1.querySelector(':scope>a')?.textContent||'').trim().replace(/\s+/g,' '); // 중분류 = li.more (depth2 패널 안) const mores=li1.querySelectorAll('li.more'); if(mores.length===0){ // li.more 없으면 depth3 직접 or 단일 for(const a of li1.querySelectorAll('ul.depth3 > li > a, ul > li > a')){ out.push({D,E:'',F:(a.textContent||'').trim().replace(/\s+/g,' '),href:a.getAttribute('href')||''}); } continue; } for(const m of mores){ const E=(m.querySelector(':scope>p')?.textContent||'').trim().replace(/\s+/g,' '); for(const a of m.querySelectorAll('ul.depth3 > li > a')){ out.push({D,E,F:(a.textContent||'').trim().replace(/\s+/g,' '),href:a.getAttribute('href')||''}); } } } return out; }""") b.close() def parse(href): href=(href or '').strip() m=re.search(r"goPage\('([A-Z]+)'\s*,\s*'([^']+)'", href) if m: typ=m.group(1); path=m.group(2) url=path if path.startswith('http') else BASE+path return typ, url if href.startswith('http'): return ('EXT' if 'komipo.co.kr' not in href else 'CONTENT'), href if href.startswith('/'): return 'CONTENT', BASE+href return '', '' tree=[] for r in rows: typ,url=parse(r['href']) mn='' m=re.search(r'mnCd=([A-Z0-9]+)',url) if m: mn=m.group(1) tree.append({'D':r['D'],'E':r['E'],'F':r['F'],'type':typ,'url':url,'mnCd':mn}) json.dump(tree,open('_komipo_tree.json','w',encoding='utf-8'),ensure_ascii=False,indent=1) from collections import Counter print('총 leaf:',len(tree)) print('대분류:',list(dict.fromkeys(t['D'] for t in tree))) print('type분포:',dict(Counter(t['type'] for t in tree))) # 대분류별 중분류 for D in dict.fromkeys(t['D'] for t in tree): es=list(dict.fromkeys(t['E'] for t in tree if t['D']==D)) print('▶',D,'중분류:',es)