Actions
새기능 #5802
완료됨새기능 #5801: 신유형개방 권리확인 사이트 수집
[신유형개방 권리확인] 전북경찰청 보도자료 수집 (410건)
시작시간:
2026/07/10
완료기한:
진척도:
0%
추정시간:
난이도:
중
설명
개요¶
전북경찰청 알림마당 > 보도자료 게시판 410건(2010-01-06 ~ 2026-07-07)을 전건 수집해 제출 양식에 기재했다.
- 목록:
https://www.jbpolice.go.kr/board/list.police?boardId=BBS_0000009&categoryCode1=1000000000000&menuCd=DOM_000000202002000000&contentsSid=61&startPage=N - 상세:
https://www.jbpolice.go.kr/board/view.police?boardId=BBS_0000009&...&dataSid=NNNNNN - 총 41페이지 (페이지당 10건)
분석¶
전자정부프레임워크 표준 게시판이 아닌 자체 구현 board.police 구조였다. 확인한 점은 다음 3가지.
- 페이징 파라미터가
pageIndex가 아니라startPage— 목록 URL에 그대로 붙여 GET하면 페이지 이동이 되어 정적 수집이 가능. - 제목이
<a>본문에는 줄임표로 들어가지만title속성에는 전체 제목이 들어 있음 → 상세페이지를 들어가지 않고도 전체 제목 확보 가능. - 게시물 고유키는
dataSid, 목록 링크가 상대경로로 나오므로 도메인을 붙여 절대경로로 보정.
처리 흐름¶
- 1~41페이지 목록 HTML을
pages/pN.html로 선다운로드 (네트워크 상황으로 파싱을 재실행해야 할 때 재요청 안 하도록 원본 보관) <tbody>영역의<tr>→<td>로 분해해 번호/제목/URL/등록일 추출- 게시물 번호 오름차순(과거→최신)으로 정렬 후 JSON 저장
- 번호 연속성 검사(누락 번호 목록 출력)로 수집 누락 확인
- 엑셀 시트에 A~F·H열 기재 + F열 하이퍼링크 재설정
핵심 코드¶
목록 수집
for p in $(seq 1 41); do
curl -s "https://www.jbpolice.go.kr/board/list.police?boardId=BBS_0000009&categoryCode1=1000000000000&menuCd=DOM_000000202002000000&contentsSid=61&startPage=$p" -o "pages/p$p.html"
done
목록 파싱 (title 속성에서 전체 제목)
import re, html as H, json
BASE = 'https://www.jbpolice.go.kr'
allrows = []
for p in range(1, 42):
s = open(f'pages/p{p}.html', encoding='utf-8').read()
seg = re.search(r'<tbody.*?</tbody>', s, re.S).group(0)
for tr in re.findall(r'<tr.*?</tr>', seg, re.S):
tds = re.findall(r'<td[^>]*>(.*?)</td>', tr, re.S)
if len(tds) < 4:
continue
num = re.sub(r'<[^>]+>', '', tds[0]).strip()
a = re.search(r'<a href="([^"]+)"\s+title="([^"]*)"', tds[1], re.S)
if not a:
continue
url = H.unescape(a.group(1)) # 상대경로
title = H.unescape(a.group(2)).strip() # title 속성 = 줄임 없는 전체 제목
if url.startswith('/'):
url = BASE + url # 절대경로 보정
date = re.sub(r'<[^>]+>', '', tds[3]).strip()
allrows.append({'num': int(num), 'title': title, 'url': url, 'date': date})
allrows.sort(key=lambda x: x['num']) # 과거→최신
json.dump(allrows, open('scraped.json', 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
누락 검사
nums = [r['num'] for r in allrows]
print('total:', len(allrows), 'unique:', len(set(nums)))
print('range:', min(nums), '-', max(nums))
print('missing:', [n for n in range(min(nums), max(nums) + 1) if n not in set(nums)])
엑셀 반영 (템플릿 서식 유지 + 하이퍼링크)
import openpyxl, datetime
from copy import copy
wb = openpyxl.load_workbook('전북경찰청 및 중앙경찰학교 크롤링.xlsx')
ws = wb['전북경찰청']
tmpl = {c: copy(ws.cell(4, c)._style) for c in range(1, 13)} # 서식 템플릿 행
for i, row in enumerate(allrows):
r = 4 + i
y, m, d = map(int, row['date'].split('-'))
vals = {1: i + 1, 2: '전북경찰청', 3: '알림마당 > 보도자료', 4: '보도자료',
5: row['title'], 6: row['url'], 8: datetime.datetime(y, m, d)}
for c in range(1, 13):
cell = ws.cell(r, c)
cell._style = copy(tmpl[c])
if c in vals:
cell.value = vals[c]
ws.cell(r, 6).hyperlink = row['url'] # F열 링크 활성화
wb.save('전북경찰청 및 중앙경찰학교 크롤링.xlsx')
사용 패키지¶
| 패키지 | 버전 | 용도 |
|---|---|---|
| Python | 3.13.0 | 실행 환경 |
| openpyxl | 3.1.5 | 엑셀 기재·서식 복사·하이퍼링크 |
| curl | - | 목록 HTML 선다운로드 |
표준 라이브러리: re / json / html / datetime / copy
특이사항¶
- 처음에 다른 기관(한국보건산업진흥원) 양식을 복사해 쓴 탓에 F열 4~406행에 KHIDI 하이퍼링크가 그대로 남아있었다. 셀 값은 전북경찰청 URL인데 클릭하면 khidi.or.kr로 이동하는 상태 → 전체 행의
hyperlink를 실제 URL로 재설정해 해결. - 이후 사이트부터는 템플릿 복사 직후 기존 하이퍼링크를 먼저 제거하고 시작하는 것을 기본 절차로 삼았다.
표시할 데이터가 없습니다.
Actions