공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
2.7 KiB
Python
70 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
import openpyxl, urllib.request, ssl, re, json, time
|
|
from urllib.parse import quote, urlsplit, urlunsplit
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
|
|
def enc(u):
|
|
p=urlsplit(u); return urlunsplit((p.scheme,p.netloc,p.path,quote(p.query,safe='=&'),p.fragment))
|
|
def get(u):
|
|
for _ in range(4):
|
|
try:
|
|
req=urllib.request.Request(enc(u),headers={'User-Agent':'Mozilla/5.0'})
|
|
return urllib.request.urlopen(req,context=ctx,timeout=20).read().decode('utf-8','replace')
|
|
except Exception: time.sleep(0.6)
|
|
return None
|
|
def board_count(h):
|
|
nums=[]
|
|
for tr in re.findall(r'<tr[^>]*>(.*?)</tr>', h, re.S):
|
|
if 'href' not in tr: continue
|
|
tds=re.findall(r'<td[^>]*>(.*?)</td>', tr, re.S)
|
|
if not tds: continue
|
|
first=re.sub(r'<[^>]+>','',tds[0]).strip().replace(',','')
|
|
if first.isdigit(): nums.append(int(first))
|
|
return (max(nums) if nums else 0), len(nums)
|
|
# empty board: has board thead (제목/작성일) but 0 data rows
|
|
def is_board_shell(h):
|
|
return bool(re.search(r'<th[^>]*>\s*제목', h)) and ('hidden-md-down' in h)
|
|
|
|
FN='제주특별자치도_서귀포시.xlsx'
|
|
wb=openpyxl.load_workbook(FN); ws=wb.active
|
|
rowsX=[]
|
|
for r in range(78, ws.max_row+1):
|
|
L=ws.cell(r,12).value; url=ws.cell(r,11).value
|
|
if L=='사이트' or not url or 'seogwipo.go.kr' not in url: continue
|
|
rowsX.append((r,url,L,ws.cell(r,13).value))
|
|
|
|
def task(item):
|
|
r,url,L,M=item
|
|
h=get(url)
|
|
if not h: return r,None
|
|
cnt,gl=board_count(h)
|
|
shell=is_board_shell(h) if cnt==0 else False
|
|
return r,(cnt,gl,shell)
|
|
|
|
res={}
|
|
with ThreadPoolExecutor(max_workers=6) as ex:
|
|
for r,d in ex.map(task, rowsX):
|
|
res[r]=d
|
|
|
|
changes=[]
|
|
for r,url,L,M in rowsX:
|
|
d=res.get(r)
|
|
if d is None: changes.append((r,'FETCHFAIL',L,M,None)); continue
|
|
cnt,gl,shell=d
|
|
if cnt>0:
|
|
newL='게시판'; newM=cnt
|
|
if L!=newL or M!=newM:
|
|
ws.cell(r,12).value=newL; ws.cell(r,13).value=newM
|
|
# if was page with N missing-> keep N; ensure O baseline if site? keep
|
|
changes.append((r, ('L:%s→게시판 '%L if L!='게시판' else '')+'M:%s→%d'%(M,newM), L,M,newM))
|
|
elif shell and L!='게시판':
|
|
ws.cell(r,12).value='게시판'; ws.cell(r,13).value=0; ws.cell(r,14).value='없음'
|
|
changes.append((r,'L:%s→게시판(빈) M0 N없음'%L,L,M,0))
|
|
wb.save(FN)
|
|
print('대상 %d행 | 변경 %d행'%(len(rowsX), len(changes)))
|
|
import openpyxl as o
|
|
w2=o.load_workbook(FN); s2=w2.active
|
|
for r,desc,oL,oM,nM in changes:
|
|
lbl=[s2.cell(r,c).value for c in (6,7,8) if s2.cell(r,c).value]
|
|
print(' r%d %s | %s'%(r,(lbl[-1] if lbl else '')[:20], desc))
|