공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
93 lines
4.2 KiB
Python
93 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""홍성 복지·보훈 섹션 F항목 하위페이지 전개(청소년복지식). r366~ 여성복지·경로복지·사회복지시설현황·바우처.
|
|
F행 G=첫 하위, 나머지 하위는 G자식 행 삽입, F병합, process_row로 L/M/N.
|
|
사용: python -X utf8 _홍성_복지하위.py [--write]
|
|
"""
|
|
import sys, os, re, shutil, importlib.util
|
|
import openpyxl
|
|
from openpyxl.worksheet.hyperlink import Hyperlink
|
|
|
|
HERE=os.path.dirname(os.path.abspath(__file__))
|
|
s=importlib.util.spec_from_file_location('m',os.path.join(HERE,'_chungnam_phase234_all.py'))
|
|
M=importlib.util.module_from_spec(s); s.loader.exec_module(M)
|
|
XLSX=r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\15.홍성군\충청남도_홍성군.xlsx'
|
|
BASE='https://www.hongseong.go.kr'
|
|
BODY=['#contents','#txt','main']
|
|
|
|
def subs_of(url):
|
|
"""페이지가 링크한 같은 섹션(sub05_01<sec>NN) 하위들, sub05번호 오름차순 (label,url)."""
|
|
soup=M.fetch(url)
|
|
if soup is None: return None
|
|
mmp=re.search(r'sub05_(\d{2})(\d{2})(\d{2})',url)
|
|
if not mmp: return None
|
|
pref='sub05_%s%s'%(mmp.group(1),mmp.group(2))
|
|
found={}
|
|
for a in soup.find_all('a',href=True):
|
|
mm=re.search(r'(sub05_\d+)\.do',a['href'])
|
|
if mm and mm.group(1).startswith(pref):
|
|
t=a.get_text(strip=True)
|
|
if t: found[mm.group(1)]=t # last-wins: 본문 타이틀이 LNB 섹션명보다 뒤(정확)
|
|
return [(found[k],BASE+'/kor/%s.do'%k) for k in sorted(found)]
|
|
|
|
def remap_insert(ws, ins, n):
|
|
ranges=[(x.min_col,x.min_row,x.max_col,x.max_row) for x in list(ws.merged_cells.ranges)]
|
|
for x in list(ws.merged_cells.ranges): ws.unmerge_cells(str(x))
|
|
ws.insert_rows(ins,n)
|
|
for mc,mr,xc,xr in ranges:
|
|
if mr>=ins: mr+=n; xr+=n
|
|
elif xr>=ins: xr+=n
|
|
ws.merge_cells(start_row=mr,start_column=mc,end_row=xr,end_column=xc)
|
|
|
|
def main():
|
|
write='--write' in sys.argv
|
|
wb=openpyxl.load_workbook(XLSX); ws=wb.active
|
|
# 복지·보훈 E블록 범위
|
|
e0=e1=None
|
|
for x in ws.merged_cells.ranges:
|
|
if x.min_col==5==x.max_col and ws.cell(x.min_row,5).value=='복지·보훈':
|
|
e0,e1=x.min_row,x.max_row
|
|
C=ws.cell(366,3).value
|
|
# 대상: r366~e1, F값 있고 L=페이지 G빈칸, 하위>1
|
|
targets=[]
|
|
for r in range(366,(e1 or ws.max_row)+1):
|
|
F=ws.cell(r,6).value; G=ws.cell(r,7).value; K=ws.cell(r,11).value; L=ws.cell(r,12).value
|
|
if F in (None,'') or G not in (None,'') or L!='페이지': continue
|
|
if not(isinstance(K,str) and 'sub05_' in K): continue
|
|
sp=subs_of(K)
|
|
if sp and len(sp)>1: targets.append((r,F,sp))
|
|
print('대상:',[(F,len(sp)) for r,F,sp in targets])
|
|
if not write:
|
|
for r,F,sp in targets:
|
|
print(' r%d %s: %s'%(r,F,[t for t,_ in sp]));
|
|
return
|
|
shutil.copy(XLSX, XLSX.replace('.xlsx','_backup_복지하위전.xlsx'))
|
|
tot=0
|
|
for r,F,sp in sorted(targets,key=lambda t:-t[0]): # bottom-up
|
|
first=sp[0]; rest=sp[1:]; n=len(rest)
|
|
ws.cell(r,7).value=first[0] # F행 G=첫 하위 라벨
|
|
if n:
|
|
remap_insert(ws, r+1, n)
|
|
for i,(lab,url) in enumerate(rest):
|
|
rr=r+1+i
|
|
out=M.process_row(url, BODY)
|
|
ws.cell(rr,3).value=C
|
|
ws.cell(rr,7).value=lab
|
|
ws.cell(rr,11).value=url
|
|
ws.cell(rr,12).value=out['L'] or '페이지'
|
|
ws.cell(rr,13).value=out['M'] if out['M']!='' else 1
|
|
ws.cell(rr,14).value=out['N']
|
|
ws.cell(rr,15).value=out['O']; ws.cell(rr,16).value=out['P']; ws.cell(rr,17).value=out['Q']
|
|
ws.row_dimensions[rr].height=15
|
|
ws.merge_cells(start_row=r,start_column=6,end_row=r+n,end_column=6) # F병합
|
|
tot+=n
|
|
print(' r%d %s +%d (G첫=%s)'%(r,F,n,first[0]))
|
|
# 하이퍼링크 전체 재구성
|
|
for r in range(3,ws.max_row+1):
|
|
v=ws.cell(r,11).value; cell=ws.cell(r,11)
|
|
if isinstance(v,str) and v.startswith('http'): cell.hyperlink=Hyperlink(ref=cell.coordinate,target=v)
|
|
else: cell.hyperlink=None
|
|
wb.save(XLSX)
|
|
print('적용: +%d행 · 하이퍼링크재구성 · 백업'%tot)
|
|
|
|
if __name__=='__main__': main()
|