- 공공기관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>
61 lines
2.7 KiB
Python
61 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
import openpyxl,sys,urllib.request,ssl,re,bs4,time
|
|
sys.stdout.reconfigure(encoding='utf-8')
|
|
ctx=ssl.create_default_context(); ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
|
|
def fetch(u,t=3):
|
|
for i in range(t):
|
|
try: return urllib.request.urlopen(urllib.request.Request(u,headers={'User-Agent':'Mozilla/5.0'}),timeout=18,context=ctx).read()
|
|
except:
|
|
if i==t-1: raise
|
|
time.sleep(1.5)
|
|
MARK=re.compile(r'open(?:type|code)_?0*([1-4])\.(?:jpg|png|gif)',re.I)
|
|
def types_in(html, soup):
|
|
ts=set()
|
|
for m in MARK.finditer(html): ts.add(int(m.group(1)))
|
|
return ts
|
|
def is_linked(soup):
|
|
for a in soup.find_all('a'):
|
|
if 'kogl' in (a.get('href','') or '').lower() and a.find('img'): return True
|
|
return False
|
|
def detail_links(listurl, soup, html):
|
|
base=listurl.rsplit('/',1)[0]+'/'
|
|
links=set()
|
|
for a in soup.find_all('a'):
|
|
hr=a.get('href','') or ''
|
|
if re.search(r'_view\.jsp|view\.jsp|View\.jsp',hr) and ('no=' in hr or 'idx=' in hr or 'seq=' in hr):
|
|
links.add(hr if hr.startswith('http') else base+hr.lstrip('/').replace('','') if hr.startswith('/') else base+hr)
|
|
# normalize
|
|
out=[]
|
|
for l in links:
|
|
if l.startswith('http'): out.append(l)
|
|
elif l.startswith('/'): out.append('https://www.kywa.or.kr'+l)
|
|
else: out.append(base+l)
|
|
return list(dict.fromkeys(out))[:10]
|
|
|
|
wb=openpyxl.load_workbook('한국청소년활동진흥원.xlsx'); ws=wb.active
|
|
out=[]
|
|
for r in range(3,ws.max_row+1):
|
|
url=ws.cell(r,11).value; L=ws.cell(r,12).value; curO=ws.cell(r,15).value
|
|
if not url or not str(url).startswith('http') or 'kywa.or.kr' not in url or L=='사이트':
|
|
continue
|
|
try:
|
|
h=fetch(url); html=h.decode('utf-8','ignore'); soup=bs4.BeautifulSoup(h,'html.parser')
|
|
ts=types_in(html,soup); linked=is_linked(soup)
|
|
src='page'
|
|
if L=='게시판':
|
|
dls=detail_links(url,soup,html)
|
|
for d in dls:
|
|
try:
|
|
hh=fetch(d); HH=hh.decode('utf-8','ignore'); ss=bs4.BeautifulSoup(hh,'html.parser')
|
|
ts|=types_in(HH,ss); linked=linked or is_linked(ss)
|
|
except: pass
|
|
src='board(%d)'%len(dls)
|
|
newO='%s유형'%(','.join(str(x) for x in sorted(ts))) if ts else '미부착'
|
|
flag='' if newO==curO else ' <<CHANGE'
|
|
out.append('r%d B%s [%s] curO=%s -> %s Q=%s (%s)%s'%(r,ws.cell(r,2).value,L,curO,newO,'Y' if linked else 'N',src,flag))
|
|
except Exception as e:
|
|
out.append('r%d ERR %s'%(r,str(e)[:40]))
|
|
open('_oscan_out.txt','w',encoding='utf-8').write('\n'.join(out))
|
|
print('\n'.join(out))
|
|
print('DONE')
|