Actions
새기능 #5857
완료됨새기능 #5801: 신유형개방 권리확인 사이트 수집
[신유형개방 권리확인] 한국동서발전 보도자료 수집 (3,076건)
시작시간:
2026/08/06
완료기한:
진척도:
100%
추정시간:
난이도:
중
설명
개요¶
한국동서발전(EWP) 홈페이지 보도자료 게시판 전건 크롤링 후, 기존 권리확인(양식) 파일을 템플릿으로 복사해 수집 결과를 자동 기재한 작업.
- 작업일: 2026-08-06
- 대상: https://www.ewp.co.kr/kor/subpage/content.html?pc=W7ADTHM4F3LZV1D51SG246L8B073MG0 (사이버홍보실 > 동서뉴스 > 보도자료)
- 수집: 3,076건 (2001-12-10 ~ 2026-08-06, 게시판 전건)
산출물¶
| 파일 | 내용 |
|---|---|
■ 권리확인(양식)_한국동서발전_보도자료_20260806.xlsm |
권리확인 양식(매크로 포함) 수집본 |
■ 권리확인(양식)_한국동서발전_보도자료_20260806.xlsx |
일반 엑셀 버전 (매크로 제거, 데이터 동일) |
기재 열: 순번(A) / 사이트명(B)=한국동서발전 / 게시판 경로(D)=사이버홍보실>동서뉴스>보도자료 / 게시판명(E)=보도자료 / 게시물제목(F) / URL주소(G, 활성 하이퍼링크) / 게시글 등록일(H) / 첨부파일여부(K) / 의견(V)='입력'
게시판 분석¶
- 자체 ASP 계열 게시판. 목록이 서버 렌더링이라 파싱 용이. 상세보기는
view(idx)JS 함수가 POST 폼(myform)을 제출하는 구조지만, 같은 파라미터를 GET 쿼리로 넣어도 동작하는 것을 확인 → 재현 가능한 상세 URL 확보.
| 항목 | 값 |
|---|---|
| 목록 URL | GET /kor/subpage/content.html?pc={게시판코드}&page={n}&pageNum=100 |
| 게시판코드(pc) | W7ADTHM4F3LZV1D51SG246L8B073MG0 |
| 페이지당 건수 | 기본 10 → pageNum=100으로 올려 31회 요청으로 전건 수집 |
| 상세 URL | GET /kor/subpage/content.html?pc={pc}&state=view&idx={게시물idx} |
| 게시물 키 | onclick="view(45237)" 의 idx |
| 전체 제목 | 목록 <a title="…"> 속성 (말줄임 무관, 상세 조회 불필요) |
| 첨부 여부 | 행 내 new_down('idx','1') Download 버튼 유무 |
| 등록일 | 목록 마지막 <td> (YYYY.MM.DD) |
수집 중 이슈¶
크롤링 도중 목록번호(no) 2개가 비어 보였는데, 마지막 페이지들을 재수집해 idx 기준으로 대조한 결과 실제 누락 없음 — 수집 중 게시물 수 재계산으로 번호만 밀린 것. (게시물 식별은 no가 아닌 idx로 관리)
엑셀 생성 방식¶
- 기존 권리확인(양식) 파일(경남경찰청본)을 복사해 템플릿으로 사용 — 매크로·수식·데이터검증(드롭다운)·서식 보존
- Excel COM(
AutomationSecurity=3, 매크로 미실행)으로 기존 데이터 행(3~358)ClearContents+ G열 하이퍼링크 삭제 - 수집 데이터 3,076행을 2차원 배열 일괄 입력(A~H) 후 G열만
Hyperlinks.Add로 링크 활성화 SaveAs FileFormat=51로 xlsx 버전 추가 생성
확장자/무결성 검증 및 발견된 문제¶
- Excel COM으로 재오픈(복구 프롬프트 여부) + openpyxl로 전행(3,076행) 셀 단위 대조 실시
- 문제 발견: 제목이 작은따옴표로 시작하는 20건(예:
'04년도 Target Budgeting 토론회 개최)에서 Excel이 선행'를 텍스트 지정 접두어로 해석해 삭제 → 해당 셀만"'" + 제목(따옴표 한 번 더)으로 재기록해 원문 복원 - 보정 후 xlsm/xlsx 모두 전행 불일치 0건, 무작위 3건 상세 URL 실접속 제목 대조 통과
코드¶
크롤러 crawl_ewp.py¶
import requests, re, json, time, html
H = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0'}
BASE = 'https://www.ewp.co.kr/kor/subpage/content.html'
PC = 'W7ADTHM4F3LZV1D51SG246L8B073MG0'
ROW = re.compile(
r'<td>(\d+)</td>\s*'
r'<td class="t_left"><a href="#" onclick="view\((\d+)\); return false;" title="([^"]*)"[^>]*>.*?</a></td>(.*?)'
r'<td>([\d.]+)</td>', re.S)
posts, seen, page = [], set(), 1
sess = requests.Session(); sess.headers.update(H)
while True:
r = sess.get(BASE, params={'pc': PC, 'page': str(page), 'pageNum': '100'}, timeout=40)
rows = ROW.findall(r.text)
new = 0
for no, idx, title, mid, date in rows:
if idx in seen: continue
seen.add(idx); new += 1
posts.append({'no': int(no), 'idx': int(idx),
'title': html.unescape(title).strip(),
'attach': 'Y' if 'new_down' in mid else '',
'date': date.strip().rstrip('.').replace('.', '-'),
'url': f'{BASE}?pc={PC}&state=view&idx={idx}'})
if not rows or new == 0: break
page += 1; time.sleep(0.4)
posts.sort(key=lambda p: p['no']) # 순번 1 = 가장 오래된 글
json.dump(posts, open('ewp_posts.json', 'w', encoding='utf-8'), ensure_ascii=False)
템플릿 복사 + 기재 build_ewp_excel.py¶
import json, shutil
import win32com.client as win32
shutil.copy2(TPL_경남양식, OUT) # 양식 통째로 복사 (매크로·서식 보존)
posts = json.load(open('ewp_posts.json', encoding='utf-8'))
excel = win32.DispatchEx('Excel.Application')
excel.AutomationSecurity = 3 # 매크로 실행 차단
wb = excel.Workbooks.Open(OUT, UpdateLinks=0)
ws = wb.Worksheets('권리확인')
excel.Calculation = -4135 # 수동 계산
# 1) 기존 데이터 제거
ws.Range(ws.Cells(3, 1), ws.Cells(358, 15)).ClearContents() # A~O
ws.Range(ws.Cells(3, 22), ws.Cells(358, 22)).ClearContents() # V
ws.Range(ws.Cells(3, 7), ws.Cells(358, 7)).Hyperlinks.Delete()
# 2) 3,076행 일괄 입력 (배열 방식 — 셀 단위 대비 수십 배 빠름)
n = len(posts)
data = [[i, '한국동서발전', None, '사이버홍보실>동서뉴스>보도자료', '보도자료',
p['title'], p['url'], p['date']] for i, p in enumerate(posts, 1)]
ws.Range(ws.Cells(3, 1), ws.Cells(2 + n, 8)).Value = data
ws.Range(ws.Cells(3, 11), ws.Cells(2 + n, 11)).Value = [[p['attach'] or None] for p in posts]
ws.Range(ws.Cells(3, 22), ws.Cells(2 + n, 22)).Value = [['입력'] for _ in posts]
# 3) G열 하이퍼링크 활성화
for i, p in enumerate(posts):
ws.Hyperlinks.Add(Anchor=ws.Cells(3 + i, 7), Address=p['url'], TextToDisplay=p['url'])
wb.Save()
wb.SaveAs(OUT_XLSX, FileFormat=51) # xlsx 버전 (51 = xlOpenXMLWorkbook)
선행 작은따옴표 보정¶
# Excel이 셀 값 선두의 '를 텍스트 지정자로 먹는 문제 → 한 번 더 붙여 원문 보존
targets = [(3 + i, p['title']) for i, p in enumerate(posts) if p['title'].startswith("'")]
for r, title in targets: # 20건
ws.Cells(r, 6).Value = "'" + title
전행 무결성 대조 (openpyxl)¶
import openpyxl
wb = openpyxl.load_workbook(path)
ws = wb['권리확인']
bad = sum(1 for i, p in enumerate(posts)
if ws.cell(3 + i, 6).value != p['title'] or ws.cell(3 + i, 7).value != p['url'])
# 보정 후 xlsm/xlsx 모두 bad == 0
표시할 데이터가 없습니다.
Actions