DB_JOB/작업파일/공공기관2/6.한국중부발전/_temp_recheck.py
hehihoho3 b0acd1e705 백업: 셀병합 정상화(D~J)+KDHC 옵션2/행높이17, 오늘(06-21) 제출 17곳 검수·압축
- 공공기관2/3 작업본 + 오늘 제출 17곳 D~J 카테고리 셀병합 정상화
- 한국지역난방공사 옵션2(고아셀 F98 수정)+전행 높이17
- 제출_프리랜서2_2026-06-21.zip 생성(17개 xlsx, 2,468행)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 13:21:26 +09:00

67 lines
3.6 KiB
Python

# -*- coding: utf-8 -*-
import openpyxl, time, json, re, ssl, urllib.request, sys
from urllib.parse import urlparse
from bs4 import BeautifulSoup
ctx=ssl.create_default_context();ctx.check_hostname=False;ctx.verify_mode=ssl.CERT_NONE
HDR={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124 Safari/537.36'}
def fetch(u): return urllib.request.urlopen(urllib.request.Request(u,headers=HDR),timeout=25,context=ctx).read()
UI=re.compile(r'banner|/common/|icon|btn|logo|bullet|sprite|blank|no_img|arrow|/dot|/bg|popup|/sns|/mark|webwatch',re.I)
DIAG=re.compile(r'조직도|체계도|순서도|흐름도|구성도|개념도|체계$|절차도|로드맵|추진체계|다이어그램|한눈|chart|graph|플랫폼\s*구축|구성$')
ws=openpyxl.load_workbook('한국중부발전.xlsx').active
rows=[]
for r in range(3,ws.max_row+1):
if all(ws.cell(r,c).value in (None,'') for c in range(2,16)): continue
rows.append((r,ws.cell(r,2).value,ws.cell(r,11).value,ws.cell(r,12).value,ws.cell(r,13).value,ws.cell(r,14).value))
out=[]
for (r,b,K,L,M,N) in rows:
if not K or 'komipo.co.kr' not in str(K): # 사이트/외부
continue
try: soup=BeautifulSoup(fetch(str(K)),'html.parser')
except Exception as e: out.append((r,b,'FETCHERR',L,M,N,str(e)[:30])); time.sleep(0.4); continue
isboard='/board/' in str(K) and ('boardMain' in str(K) or 'boardList' in str(K))
isfr='/fr/' in str(K)
rL=rM=rN=None
if isboard or isfr:
em=soup.select_one('div.total em.count') or soup.select_one('.total .count')
rM=int(re.sub(r'[^0-9]','',em.get_text())) if em else 0
rL='게시판'
cont=soup.select_one('#content') or soup
thumbs=[im for im in cont.find_all('img') if 'getImage' in im.get('src','') and not UI.search(im.get('src',''))]
rN='없음' if rM==0 else ('어문,이미지' if thumbs else '어문')
else:
# in-page tabs?
ntab=0
for ul in soup.find_all('ul'):
cls=' '.join(ul.get('class') or [])
if 'tab' in cls and 'tab_link' not in cls:
tt=[li for li in ul.find_all('li',recursive=False) if li.find('a') and (li.find('a').get('data-tab') or (li.find('a').get('href','') or '').startswith('#'))]
if len(tt)>=2: ntab=max(ntab,len(tt))
rL='페이지'; rM=ntab if ntab>=2 else 1
cont=soup.select_one('#content') or soup.select_one('div.contents')
real=[]
if cont:
for im in cont.find_all('img'):
src=im.get('src','');alt=im.get('alt','')
if UI.search(src): continue
if 'getImage' in src and ('코로나' in alt or '정규직' in alt): continue
real.append((src,alt))
diag_only=real and all(DIAG.search(a or '') for s,a in real)
rN='어문,이미지' if (real and not diag_only) else '어문'
# compare (normalize trailing spaces)
sN=(N or '').strip()
flags=[]
if rL!=(L or '').strip(): flags.append('L:%s!=%s'%(L,rL))
if rM!=M: flags.append('M:%s!=%s'%(M,rM))
if rN!=sN: flags.append('N:%s!=%s'%(sN,rN))
if flags:
out.append((r,b,'DIFF',L,M,sN,rL,rM,rN,' '.join(flags),str(K)[:46],[a or s.split('/')[-1] for s,a in (real if not (isboard or isfr) else [])][:4]))
time.sleep(0.55)
json.dump(out,open('recheck.json','w',encoding='utf-8'),ensure_ascii=False,indent=1,default=str)
print('대조 mismatch:',len([x for x in out if x[2]=='DIFF']),'/ fetch err:',len([x for x in out if x[2]=='FETCHERR']))
for x in out:
if x[2]=='DIFF':
print(f'r{x[0]} b{x[1]} [{x[9]}] {x[10]} {x[11]}')
else:
print(f'r{x[0]} b{x[1]} FETCHERR {x[6]}')