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