프로젝트

일반

사용자정보

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가지.

  1. 페이징 파라미터가 pageIndex가 아니라 startPage — 목록 URL에 그대로 붙여 GET하면 페이지 이동이 되어 정적 수집이 가능.
  2. 제목이 <a> 본문에는 줄임표로 들어가지만 title 속성에는 전체 제목이 들어 있음 → 상세페이지를 들어가지 않고도 전체 제목 확보 가능.
  3. 게시물 고유키는 dataSid, 목록 링크가 상대경로로 나오므로 도메인을 붙여 절대경로로 보정.

처리 흐름

  1. 1~41페이지 목록 HTML을 pages/pN.html 로 선다운로드 (네트워크 상황으로 파싱을 재실행해야 할 때 재요청 안 하도록 원본 보관)
  2. <tbody> 영역의 <tr><td> 로 분해해 번호/제목/URL/등록일 추출
  3. 게시물 번호 오름차순(과거→최신)으로 정렬 후 JSON 저장
  4. 번호 연속성 검사(누락 번호 목록 출력)로 수집 누락 확인
  5. 엑셀 시트에 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

내보내기 Atom PDF