공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
4.6 KiB
Python
81 lines
4.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
import openpyxl, glob, os, re, json, shutil
|
|
from copy import copy
|
|
from openpyxl.styles import PatternFill
|
|
BLUE=PatternFill(fill_type='solid', fgColor='FFBDD7EE'); MAXC=27
|
|
BASE=os.path.dirname(os.path.abspath(__file__))
|
|
d=[x for x in glob.glob(os.path.join(BASE,'3.*')) if os.path.isdir(x)][0]
|
|
xp=[p for p in glob.glob(os.path.join(d,'*.xlsx')) if not os.path.basename(p).startswith(('_','~')) and 'conflict' not in os.path.basename(p)][0]
|
|
menu=json.load(open(os.path.join(BASE,'_hira_menu.json'),encoding='utf-8'))
|
|
def Lof(u):
|
|
if 'hira.or.kr' not in u: return '사이트'
|
|
if re.search(r'(List\.do|bbsDummy|getReportList|getHistoryList|getExplainList|lawInfoList|bfrInfoList|drgAmtsList|NpayInfoList)', u): return '게시판'
|
|
return '페이지'
|
|
# normalize None-E -> the leaf is 중분류 (E), F empty
|
|
rows=[]
|
|
for m in menu:
|
|
D=m['D']; E=m['E']; F=m['F']; u=m['url']
|
|
if E is None: E=F; F=None # 중분류 직링크
|
|
L=Lof(u)
|
|
rows.append({'D':D,'E':E,'F':F,'url':u,'L':L,'M':(0 if L=='게시판' else (None if L=='사이트' else 1)),
|
|
'N':(None if L=='사이트' else '어문'),'O':(None if L=='사이트' else '미부착'),
|
|
'S':('외부링크' if L=='사이트' else None),'new':True})
|
|
# preserve from old scrape: 관련사이트(외부포털) + 이용안내(약관/정책)
|
|
mt=os.path.getmtime(xp); wb=openpyxl.load_workbook(xp); ws=wb.active
|
|
def eff(r,c):
|
|
v=ws.cell(r,c).value
|
|
if v is not None: return v
|
|
for mr in ws.merged_cells.ranges:
|
|
if mr.min_col==c and mr.min_row<=r<=mr.max_row: return ws.cell(mr.min_row,c).value
|
|
PORTAL_KW=['포털','시스템','리포지터리','학술지','도서관','거짓청구','명단','헬프라인','익명신고','조회시스템']
|
|
POLICY={'이용약관','개인정보처리방침','저작권 정책','고정형·이동형 영상정보처리기기 운영·관리 방침','오시는길','찾아오시는 길','고객지원'}
|
|
seen=set(r['url'].split('?')[0] for r in rows)
|
|
data=[r for r in range(3,ws.max_row+1) if ws.cell(r,2).value is not None]
|
|
extra=[]
|
|
for r in data:
|
|
D=eff(r,4); u=ws.cell(r,11).value
|
|
if not u or 'http' not in str(u): continue
|
|
base=str(u).split('?')[0]
|
|
if base in seen: continue
|
|
# 관련사이트: external OR portal-like
|
|
if (('hira.or.kr' not in str(u)) or any(k in str(D) for k in PORTAL_KW)) and ws.cell(r,12).value=='사이트':
|
|
extra.append({'D':'관련사이트','E':D,'F':None,'url':u,'L':'사이트','M':None,'N':None,'O':None,'S':'외부링크','new':True}); seen.add(base)
|
|
elif D in POLICY:
|
|
extra.append({'D':'이용안내','E':D,'F':None,'url':u,'L':ws.cell(r,12).value or '페이지','M':ws.cell(r,13).value,'N':ws.cell(r,14).value or '어문','O':'미부착','S':None,'new':True}); seen.add(base)
|
|
rows+=extra
|
|
print('심평원 신규 시트: 메뉴 %d + 보존(관련사이트/이용안내) %d = %d행'%(len(rows)-len(extra),len(extra),len(rows)))
|
|
# build sheet: clear data, write rows, template style from old row3
|
|
tpl={c:copy(ws.cell(3,c)._style) for c in range(1,MAXC+1)}
|
|
for mr in list(ws.merged_cells.ranges):
|
|
if mr.min_row>=3: ws.unmerge_cells(str(mr))
|
|
for r in range(3, ws.max_row+1):
|
|
for c in range(1,MAXC+1):
|
|
cell=ws.cell(r,c); cell.value=None; cell.hyperlink=None; cell.fill=PatternFill(fill_type=None)
|
|
n=len(rows)
|
|
for i,rc in enumerate(rows):
|
|
r=3+i
|
|
for c in range(1,MAXC+1): ws.cell(r,c)._style=copy(tpl[c])
|
|
ws.cell(r,2).value=i+1; ws.cell(r,3).value='건강보험심사평가원'
|
|
ws.cell(r,4).value=rc['D']; ws.cell(r,5).value=rc['E']; ws.cell(r,6).value=rc['F']
|
|
ws.cell(r,11).value=rc['url']; ws.cell(r,11).hyperlink=rc['url']
|
|
ws.cell(r,12).value=rc['L']; ws.cell(r,13).value=rc['M']; ws.cell(r,14).value=rc['N']; ws.cell(r,15).value=rc['O']; ws.cell(r,19).value=rc['S']
|
|
for c in range(4,16): ws.cell(r,c).fill=BLUE
|
|
ws.row_dimensions[r].height=15
|
|
def rem(col,sc):
|
|
r=3
|
|
while r<3+n:
|
|
v=ws.cell(r,col).value
|
|
if v is None or v=='': r+=1; continue
|
|
r2=r
|
|
while r2+1<3+n and ws.cell(r2+1,col).value==v and all(ws.cell(r2+1,s).value==ws.cell(r,s).value for s in sc): r2+=1
|
|
if r2>r:
|
|
for rr in range(r+1,r2+1): ws.cell(rr,col).value=None
|
|
ws.merge_cells(start_row=r,start_column=col,end_row=r2,end_column=col)
|
|
r=r2+1
|
|
rem(6,[4,5]); rem(5,[4]); rem(4,[])
|
|
if os.path.getmtime(xp)!=mt: print('ABORT'); raise SystemExit(1)
|
|
shutil.copy(xp, os.path.join(d,'_backup',os.path.basename(xp).replace('.xlsx','_backup_재수집전.xlsx')))
|
|
wb.save(xp)
|
|
bs=[ws.cell(r,2).value for r in range(3,3+n)]
|
|
print('saved %d행 B연속%s 대분류:'%(n,bs==list(range(1,n+1))), list(dict.fromkeys(r['D'] for r in rows)))
|