공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
3.3 KiB
Python
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)
|