# -*- coding: utf-8 -*- """ESG 마이크로사이트 추출 + 메인 트리에 병합 → _komipo_tree.json 갱신""" 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' 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 '','' 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/esg/main/main.do',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,' '); li1.querySelectorAll('li.more').forEach(m=>{const E=(m.querySelector(':scope>p')?.textContent||'').trim().replace(/\s+/g,' ');m.querySelectorAll('ul.depth3>li>a').forEach(a=>out.push({E2:D,F2:E,G2:(a.textContent||'').trim().replace(/\s+/g,' '),href:a.getAttribute('href')||''}));}); } return out; }""") b.close() esg=[] 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) # D=ESG경영, E=esg대분류, F=esg중분류, G=esg소분류 esg.append({'D':'ESG경영','E':r['E2'],'F':r['F2'],'G':r['G2'],'type':typ,'url':url,'mnCd':mn}) tree=json.load(open('_komipo_tree.json',encoding='utf-8')) tree=[t for t in tree if t['D']!='ESG경영'] # 빈 ESG 제거 # G 키 없는 기존 항목에 G='' 추가 for t in tree: t.setdefault('G','') # ESG경영 위치: 원래 5번째 대분류였음 → 순서 유지 위해 기업홍보 앞에 삽입 order=['소통채널','회사소개','기업지원','고객지원','ESG경영','기업홍보'] merged=[] for D in order: if D=='ESG경영': merged+=esg else: merged+=[t for t in tree if t['D']==D] json.dump(merged,open('_komipo_tree.json','w',encoding='utf-8'),ensure_ascii=False,indent=1) from collections import Counter print('ESG leaf:',len(esg),'| 최종 트리:',len(merged)) print('대분류순서:',list(dict.fromkeys(t['D'] for t in merged))) print('type:',dict(Counter(t['type'] for t in merged))) print('4단(G있음):',sum(1 for t in merged if t.get('G')))