DB_JOB/작업파일/완료/광역_사이트맵/충청북도/_cy3_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

61 lines
3.0 KiB
Python

# -*- coding: utf-8 -*-
# 청양 133~385 본문탭(ul.slave_tab 등) 전수 스캔
import openpyxl, json, io, sys, time
from urllib.parse import urljoin, urlparse
from playwright.sync_api import sync_playwright
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
F=r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\13.청양군\충청남도_청양군.xlsx'
wb=openpyxl.load_workbook(F); ws=wb.active
rows=[]
for r in range(133,386):
b=ws.cell(r,2).value
if b is None: continue
hl=ws.cell(r,11).hyperlink; u=(hl.target if hl else ws.cell(r,11).value) or ''
L=ws.cell(r,12).value
lab=str(ws.cell(r,6).value or ws.cell(r,7).value or ws.cell(r,5).value or '')
rows.append((r,b,lab,u,L))
print('대상',len(rows),flush=True)
# 본문 탭: slave_tab/basic_tab/tab류 ul. LNB제외 위해 #contents/.contents 내부만
JS=r'''()=>{
let main=document.querySelector('#contents,.contents,.sub_contents,.sub_container,.contents_area,#content,.content_area,#container');
if(!main) main=document.body;
const out=[];
const uls=main.querySelectorAll('ul[class*=slave_tab],ul[class*=basic_tab],ul.tab,ul[class*=tab_],ul[class*=_tab],.tab_menu ul,.content_tab ul,.tab_wrap ul');
uls.forEach(ul=>{
// LNB류 배제
if(ul.closest('.lnb,.snb,.gnb,nav,.lnb_depth2__list,.lnb_depth3__list')) return;
const cls=ul.className||'';
const items=[];
ul.querySelectorAll(':scope > li > a').forEach(a=>{
items.push({t:(a.innerText||'').trim().replace(/\s+/g,' '), href:a.getAttribute('href'), blank:(a.getAttribute('target')||'')==='_blank' || /새창/.test(a.getAttribute('title')||''), on:/\bon\b|active|current/.test(a.parentElement.className||'')});
});
if(items.length) out.push({cls,n:items.length,items});
});
return out;
}'''
def nav(pg,u):
for _ in range(2):
try: pg.goto(u,wait_until='domcontentloaded',timeout=20000); pg.wait_for_timeout(1300); return True
except Exception: time.sleep(1)
return False
res={}
with sync_playwright() as p:
b=p.chromium.launch(); pg=b.new_page(viewport={'width':1300,'height':2200}); pg.set_default_timeout(20000)
for r,bn,lab,u,L in rows:
if not u.startswith('http'): continue
try:
if nav(pg,u):
tabs=pg.evaluate(JS)
# 의미있는 탭(2개+)만
tabs=[t for t in tabs if t['n']>=2]
if tabs:
res[r]={'b':bn,'lab':lab,'u':u,'L':L,'tabs':tabs}
for t in tabs:
names=' | '.join('%s%s%s'%(''if it['on']else'',it['t'][:14],'(새창)'if it['blank']else'') for it in t['items'])
print('r%d B%s %-16s [%s n%d] %s'%(r,bn,lab[:16],t['cls'][:18],t['n'],names),flush=True)
except Exception as e:
print('r%d ERR %s'%(r,str(e)[:30]),flush=True)
b.close()
json.dump(res,open('_cy3_tabs.json','w',encoding='utf-8'),ensure_ascii=False,indent=1)
print('\n탭보유 행수:',len(res))