DB_JOB/_스크립트/_gongju_navcount.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

92 lines
3.1 KiB
Python

# -*- coding: utf-8 -*-
"""공주시 전용: 본문에 인페이지 앵커 탭(ul.tab-ul 안 a[href^="#"], 예: #nav1~4)이 있는
페이지는 1행 유지하되 수량(M, 13열)을 그 탭 개수로 기입.
판별: class 에 'tab-ul' 포함한 ul 안에서 href 가 '#' 로 시작하는 탭 <a> 개수(>=2).
한 페이지에 그런 탭그룹이 여럿이면 가장 큰 그룹의 탭 수.
사용: python -X utf8 _gongju_navcount.py [--write]
"""
import sys, warnings
from concurrent.futures import ThreadPoolExecutor, as_completed
import openpyxl, requests, shutil
from bs4 import BeautifulSoup
warnings.filterwarnings('ignore')
XLSX = r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\2.공주시\충청남도_공주시.xlsx'
DOMAIN = 'gongju.go.kr'
H = {'User-Agent': 'Mozilla/5.0 Chrome/120 Safari/537.36'}
def nav_count(html):
soup = BeautifulSoup(html, 'html.parser')
best = 0
for ul in soup.find_all('ul'):
cls = ' '.join(ul.get('class') or []).lower()
if 'tab-ul' not in cls:
continue
anchors = [a for a in ul.find_all('a')
if (a.get('href') or '').strip().startswith('#') and a.get_text(strip=True)]
if len(anchors) >= 2:
best = max(best, len(anchors))
return best
def fetch(r, u):
try:
x = requests.get(u, headers=H, timeout=15, verify=False)
return r, u, x.content
except Exception:
return r, u, None
def main():
write = '--write' in sys.argv
wb = openpyxl.load_workbook(XLSX)
ws = wb.active
targets = []
for r in range(3, ws.max_row + 1):
u = ws.cell(r, 11).value
if isinstance(u, str) and DOMAIN in u:
targets.append((r, u))
print(f'스캔 대상(동일도메인): {len(targets)}')
res = {}
with ThreadPoolExecutor(max_workers=8) as ex:
for f in as_completed([ex.submit(fetch, r, u) for r, u in targets]):
r, u, html = f.result()
if html:
c = nav_count(html)
if c >= 2:
res[r] = (u, c)
print(f'\n인페이지 탭(#) 보유 페이지: {len(res)}')
print(f"{'':>4} {'현L':<5}{'현M':>4}{'새M':>4} F/카테고리 | URL")
print('-' * 90)
chg = 0
for r in sorted(res):
u, c = res[r]
L = ws.cell(r, 12).value or ''
M = ws.cell(r, 13).value
cat = ws.cell(r, 6).value or ws.cell(r, 5).value or ws.cell(r, 4).value or ''
mark = '' if str(M) == str(c) else ''
if str(M) != str(c):
chg += 1
print(f"{r:>4} {str(L):<5}{str(M):>4}{c:>4}{mark} {cat} | {u}")
if write:
ws.cell(r, 13).value = c
print('-' * 90)
print(f'변경 대상: {chg}')
if write and chg:
bak = XLSX.replace('.xlsx', '_backup_navcount전.xlsx')
shutil.copy(XLSX, bak)
wb.save(XLSX)
print(f'저장 완료. 백업: {bak}')
elif not write:
print('(DRY — 실제 기입하려면 --write)')
if __name__ == '__main__':
main()