DB_JOB/작업파일/완료/광역_사이트맵/제주특별자치도/1.서귀포시/_tabscan.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

51 lines
2.3 KiB
Python

# -*- coding: utf-8 -*-
import urllib.request, ssl, re, json, time
from urllib.parse import quote, urlsplit, urlunsplit
from concurrent.futures import ThreadPoolExecutor
ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
def enc(u):
p=urlsplit(u); return urlunsplit((p.scheme,p.netloc,p.path,quote(p.query,safe='=&'),p.fragment))
def get(u):
for _ in range(3):
try:
req=urllib.request.Request(enc(u),headers={'User-Agent':'Mozilla/5.0'})
return urllib.request.urlopen(req,context=ctx,timeout=18).read().decode('utf-8','replace')
except Exception: time.sleep(0.6)
return None
rows={x['r']:x for x in json.load(open('_sgp_rows.json',encoding='utf-8'))}
# pages+boards >=18, seogwipo internal
targets=[x for x in rows.values() if x['r']>=18 and x['L'] in ('페이지','게시판') and x['url'] and 'seogwipo.go.kr' in x['url'] and '/tool/' not in x['url']]
def clean(t): return re.sub(r'\s+',' ',re.sub(r'<[^>]+>','',t)).strip()
def task(x):
h=get(x['url'])
if not h: return x['r'],{'fetch':False}
# find tab-menu uls (depth1 candidates): ul with class containing tab-menu OR id=sources
res=[]
for m in re.finditer(r'<ul[^>]*(?:id="sources"|class="[^"]*tab-menu[^"]*")[^>]*>(.*?)</ul>', h, re.S):
block=m.group(1)
lis=re.findall(r'<a[^>]+href="([^"]+)"[^>]*>(.*?)</a>', block, re.S)
lis=[(href,clean(t)) for href,t in lis if clean(t)]
if len(lis)>=2:
res.append(lis)
return x['r'],{'fetch':True,'tabgroups':res}
out={}
with ThreadPoolExecutor(max_workers=8) as ex:
for r,d in ex.map(task, targets):
out[r]=d
json.dump(out, open('_tabscan.json','w',encoding='utf-8'), ensure_ascii=False)
# report rows with tab groups
fails=[r for r,d in out.items() if not d.get('fetch')]
print('스캔 %d행 | fail %d'%(len(out),len(fails)), fails[:10])
print('=== 본문 탭그룹(ul tab-menu/sources >=2탭) 보유 행 ===')
for r in sorted(out):
tg=out[r].get('tabgroups',[])
if tg:
lbl=[m for m in rows[r]['menu'] if m]
# describe each group
desc=' || '.join('['+','.join(t for _,t in g[:6])[:60]+(' +%d'%(len(g)-6) if len(g)>6 else '')+']' for g in tg)
print(' r%d %s (%s) : %s'%(r,(lbl[-1] if lbl else '')[:16], rows[r]['L'], desc))