DB_JOB/작업파일/완료/공공기관/_gugak_subnav_scan.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

56 lines
3.3 KiB
Python

# -*- coding: utf-8 -*-
# 국악방송(27) 전 ?sub_num= 페이지의 좌측 ul.sub_menu 형제그룹 스캔 → 시트 미존재 sub_num 보고.
import openpyxl, glob, os, re, urllib.request, ssl, http.cookiejar, time
from bs4 import BeautifulSoup
ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
cj=http.cookiejar.CookieJar(); op=urllib.request.build_opener(urllib.request.HTTPSHandler(context=ctx),urllib.request.HTTPCookieProcessor(cj))
op.addheaders=[('User-Agent','Mozilla/5.0')]
BASE='http://www.igbf.kr'
def fixdom(u): return str(u).replace('https://new.igbf.kr','http://www.igbf.kr').replace('http://new.igbf.kr','http://www.igbf.kr')
def g(u):
try: return op.open(fixdom(u),timeout=20).read().decode('utf-8','replace')
except Exception: return ''
DIR=os.path.dirname(os.path.abspath(__file__))
d=[x for x in glob.glob(os.path.join(DIR,'27.*')) if os.path.isdir(x)][0]
xp=[p for p in glob.glob(os.path.join(d,'*.xlsx')) if not os.path.basename(p).startswith(('_','~')) and 'conflict' not in os.path.basename(p) and 'backup' not in p][0]
ws=openpyxl.load_workbook(xp).active
def eff(r,c):
v=ws.cell(r,c).value
if v is not None: return v
for mr in ws.merged_cells.ranges:
if mr.min_col==c and mr.min_row<=r<=mr.max_row: return ws.cell(mr.min_row,c).value
data=[r for r in range(3,ws.max_row+1) if ws.cell(r,2).value is not None]
def subnum(u):
m=re.search(r'[?&]sub_num=(\d+)',str(u)); return m.group(1) if m else None
sheet_sn=set(subnum(ws.cell(r,11).value) for r in data if subnum(ws.cell(r,11).value))
# 대상: ?sub_num= 단순페이지(program 제외)
targets=[r for r in data if re.search(r'gugak_web/\?sub_num=\d+',str(ws.cell(r,11).value or '')) and 'program' not in str(ws.cell(r,11).value or '')]
print('대상 %d페이지 sub_menu 스캔...'%len(targets))
seen_group=set(); reports=[]
for r in targets:
h=g(ws.cell(r,11).value)
if not h: continue
s=BeautifulSoup(h,'html.parser')
cursn=subnum(ws.cell(r,11).value)
# 모든 ul.sub_menu / ul.third_menu 그룹 수집
for ul in s.select('ul.sub_menu, ul.third_menu'):
items=[]
for a in ul.find_all('a',href=True):
sn=subnum(a['href']); t=re.sub(r'\s+',' ',a.get_text()).strip()
if sn and t: items.append((sn,t))
if len(items)<2: continue
key=tuple(sn for sn,_ in items)
if key in seen_group: continue
seen_group.add(key)
missing=[(sn,t) for sn,t in items if sn not in sheet_sn]
cur=' '.join(str(x) for x in [eff(r,4),eff(r,5),ws.cell(r,6).value] if x)
contains_cur = cursn in [sn for sn,_ in items]
reports.append((r,cur,cursn,items,missing,contains_cur))
if missing:
print('r%d [%s] (cur=%s) 그룹 %d개 미존재 %d: %s'%(r,cur,cursn,len(items),len(missing),' / '.join('%s(%s)%s'%(t,sn,'' if sn not in sheet_sn else '') for sn,t in items)))
print('\n=== 누락 형제 있는 그룹 ===')
for r,cur,cursn,items,missing,cc in reports:
if missing: print('r%d [%s] cur자신포함=%s: +%d%s'%(r,cur,cc,len(missing),', '.join('%s(%s)'%(t,sn) for sn,t in missing)))
import json
json.dump([(r,cur,cursn,items,missing,cc) for r,cur,cursn,items,missing,cc in reports],open(os.path.join(DIR,'_gugak_subnav.json'),'w',encoding='utf-8'),ensure_ascii=False)