DB_JOB/작업파일/공공기관2/_kesco_merge_extra.py
hehihoho3 df16c98366 백업: DB수집 전체 스냅샷 (공공기관2 정리 전)
공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:15:40 +09:00

55 lines
2.8 KiB
Python

# -*- coding: utf-8 -*-
"""정보공개(info포털 #gnb) 하위 + 전국사업소 13본부를 _gnb\1.json에 보완."""
import sys, io, json
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"
data = json.load(open(GNB, encoding='utf-8'))
rows = data['gnb']
# 전국사업소 13본부 (GNB 기존값)
offices = [
("서울본부","2100000"),("대구경북본부","3500000"),("광주전남본부","4500000"),
("경기본부","5500000"),("강원본부","6500000"),("전북본부","7500000"),
("제주본부","8500000"),("부산울산본부","3100000"),("인천본부","4100000"),
("대전세종충남본부","5100000"),("경기북부본부","6100000"),("충북본부","7100000"),
("경남본부","8100000"),
]
INFO_JS = """
() => {
const cont=document.querySelector('#gnb');
if(!cont) return [];
function labelA(li){for(const a of li.querySelectorAll('a,button')){let p=a.parentElement,ins=false;while(p&&p!==li){if(p.tagName==='UL'){ins=true;break;}p=p.parentElement;}if(!ins&&(a.textContent||'').trim())return a;}return null;}
function topUls(el){return [...el.querySelectorAll('ul')].filter(ul=>{let p=ul.parentElement;while(p&&p!==el){if(p.tagName==='UL')return false;p=p.parentElement;}return true;});}
const out=[];
function walk(ul,depth){[...ul.children].filter(li=>li.tagName==='LI').forEach(li=>{const a=labelA(li);if(a){const l=(a.textContent||'').trim().replace(/\\s+/g,' ');let h=a.tagName==='A'?(a.href||''):'';if(l)out.push({depth,label:l,href:h});}topUls(li).forEach(s=>walk(s,depth+1));});}
(cont.tagName==='UL'?[cont]:topUls(cont)).forEach(u=>walk(u,1));
return out;
}
"""
# 새 rows 구성: 기존 rows를 돌며 전국사업소 depth1 뒤에 본부 삽입, 정보공개 depth1 뒤에 info트리 삽입
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()
pg.goto('https://www.kesco.or.kr/info/main.do', wait_until='domcontentloaded', timeout=30000); pg.wait_for_timeout(2000)
info=pg.evaluate(INFO_JS)
br.close()
print('정보공개 info #gnb', len(info), '항목')
new=[]
for r in rows:
new.append(r)
if r['depth']==1 and r['label']=='전국사업소':
for nm,code in offices:
new.append({'depth':2,'label':nm,'href':f'https://www.kesco.or.kr/office/main.do?bonbu_code={code}'})
if r['depth']==1 and r['label']=='정보공개':
for it in info:
new.append({'depth':1+it['depth'], 'label':it['label'], 'href':it['href']})
data['gnb']=new
json.dump(data, open(GNB,'w',encoding='utf-8'), ensure_ascii=False, indent=1)
print('', len(new), '행 (정보공개+전국사업소 보완)')