import sys, io, re, ssl, json, urllib.request sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') ctx = ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE BASE='https://www.jangsu.go.kr/index.jangsu?menuCd=' def fetch(cd, tries=3): for i in range(tries): try: return urllib.request.urlopen(urllib.request.Request(BASE+cd, headers={'User-Agent':'Mozilla/5.0'}), context=ctx, timeout=40).read().decode('utf-8','replace') except Exception as e: if i==tries-1: raise # 대분류/중분류 라벨 — location nav(현재 위치) 또는 breadcrumb에서 def labels(cd): h=fetch(cd) # breadcrumb: class="location" 안의 텍스트들 loc=re.search(r'class="(?:location|path|breadcrumb)[^"]*"(.*?)', h, re.S) crumbs=[] if loc: crumbs=[re.sub(r'<[^>]+>','',x).strip() for x in re.findall(r'<(?:li|a|span)[^>]*>(.*?)', loc.group(1))] crumbs=[c for c in crumbs if c and c not in ('홈','HOME','home')] # title t=re.search(r'([^<|]+)', h) return crumbs, (t.group(1).strip() if t else '') print('=== 누락 대분류 라벨 (108/107/303 등) ===') for d in ['107','108','303','116','401','404','405']: try: cr,ti = labels(d+'000000000') print(f' 대{d}: title={ti!r} crumbs={cr[:3]}') except Exception as e: print(f' 대{d}: ERR {e}') # 중분류 라벨도 location에서 확인 (108001 등) print('=== 108 중분류 라벨 표본 ===') for cd in ['108001001000','108002009000','108006008000']: cr,ti=labels(cd); print(f' {cd}: title={ti!r} crumbs={cr}')