vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
흩어진 조직의 공지를 한 편의 보고서로. 정부·공공기관의 RSS/OpenAPI 는 물론, 한국외국어대학교처럼 본부·처·팀이 홈페이지를 따로 쓰는 조직도 한 기관으로 묶어 수집합니다. 필요한 목적 (고용·장학·정부투자…)만 골라 브리프로 만들고, 모든 출력에 출처와 공공누리(KOGL) 등급을 남깁니다. Markdown · HTML · JSON, 브라우저에서 클릭으로 쓰는 로컬 웹 UI(--serve), 그리고 휴대폰에서 주소 하나로 쓰는 웹 버전 (정부 65곳 + 한국장학재단 + 전국 대학·전문대 356곳, Vercel 무료 배포)까지 — 런타임 의존성 0. 📱 휴대폰으로 바로 쓰려면 → 휴대폰에서 쓰기 — 웹 버전 정부·지자체 공지는 부처마다 흩어진 RSS·공공데이터포털에 조각나 있고, 각 자료의 재이용 조건(공공누리 유형) 은 화면 어딘가에 작게 표기돼 실무에서 놓치기 쉽습니다. open_site_clipper는 이 둘을 한 번에 해결합니다.README 전문 보기 ↗
흩어진 조직의 공지를 한 편의 보고서로.
정부·공공기관의 RSS/OpenAPI 는 물론, 한국외국어대학교처럼 본부·처·팀이
홈페이지를 따로 쓰는 조직도 한 기관으로 묶어 수집합니다. 필요한 목적
(고용·장학·정부투자…)만 골라 브리프로 만들고, 모든 출력에 출처와
공공누리(KOGL) 등급을 남깁니다. Markdown · HTML · JSON, 브라우저에서
클릭으로 쓰는 로컬 웹 UI(--serve), 그리고 휴대폰에서 주소 하나로 쓰는 웹 버전
(정부 65곳 + 한국장학재단 + 전국 대학·전문대 356곳, Vercel 무료 배포)까지 — 런타임 의존성 0.
📱 휴대폰으로 바로 쓰려면 → 휴대폰에서 쓰기 — 웹 버전
정부·지자체 공지는 부처마다 흩어진 RSS·공공데이터포털에 조각나 있고, 각
자료의 재이용 조건(공공누리 유형) 은 화면 어딘가에 작게 표기돼 실무에서
놓치기 쉽습니다. open_site_clipper는 이 둘을 한 번에 해결합니다.
pip install 후 바로 실행--input)--state로 이전 실행에 없던 공지만 🆕 표기, --only-new 필터$title $body_md 마커 치환으로 조직 서식 그대로 출력--theme)--deep-links)--query 고용 한 줄로 관련 공지만(동의어 자동 확장, 파일 불필요)--serve 한 번이면 브라우저에서 조직을 골라 클릭으로 수집·검색 (127.0.0.1 전용)--discover)--group-by org)--jobs --delay)--check-access)kind: "govorg")kind: "govweb")필요한 것: Python 3.10 이상 (없으면 python.org에서 설치 — Windows 는 설치 중 "Add Python to PATH" 를 반드시 체크).
git clone https://github.com/corey1-cmd/open_site_clipper.git
cd open_site_clipper
dir(Windows) / ls(Mac) 했을 때 pyproject.toml·src·examples
가 보이는 위치가 맞습니다. 한 겹 더 안쪽 폴더에 있으면 cd 로 더 들어가세요.Windows (명령 프롬프트)
python -m venv .venv
.venv\Scripts\activate
pip install -e ".[dev]"
Mac / Linux (터미널)
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
가운데 줄이 성공하면 프롬프트 앞에 (.venv) 가 붙습니다. 이후 새 터미널을 열 때마다
그 activate 줄만 다시 실행하면 됩니다.
open_site_clipper --version # open_site_clipper 0.27.0
python -m pytest -q # 421 passed (인터넷 불필요)
open_site_clipper --serve # 브라우저가 http://127.0.0.1:8765 로 자동으로 열립니다
명령줄이 편하면 아래 빠른 시작의 예시를 쓰세요. --serve 사용법은
로컬 웹 UI 참고.
같은 수집기를 휴대폰 브라우저에서 씁니다. Vercel(무료)에 한 번 올리면 주소 하나를 나눠 주는 것으로 끝납니다 — 받는 사람은 아무것도 설치하지 않습니다.
화면에서 하는 일:
vercel.json 이 서울 리전(icn1)·함수 300초·정적 화면 폴더를 정합니다.https://<프로젝트>.vercel.app)를 휴대폰에서 열고 공유 메뉴 → 홈 화면에 추가.이후에는 GitHub 에 올릴 때마다 자동으로 다시 배포됩니다.
처음에는 기관마다 홈에서 게시판을 찾느라 수십 초가 걸립니다. 배포한 서버로 전 기관을 한 번 점검해 공지가 실제로 나온 게시판 주소를 저장해 두면, 다음부터는 그 주소만 엽니다.
python scripts/bake_routes.py https://<프로젝트>.vercel.app # 국내망 불필요(점검은 서버가 함)
git add src/open_site_clipper/data/route-cache.json docs/ && git commit -m "경로 캐시" && git push
docs/실측-점검-날짜.md 에 묶음별 성공 수와 못 모은 곳의 사유가 남습니다. 게시판 주소가
바뀌어 캐시가 0건을 내면 서버가 그 자리에서 다시 찾습니다(느려질 뿐 틀리지 않음).
현재 저장된 캐시(2026-10-11 실측, 서울 리전·기관당 60초·최근 30일) — docs/실측-점검-2026-10-11.md
| 묶음 | 점검 | 글 있음 | 연결(기간 내 새 글 없음) | 못 모음 | 30일 글 |
|---|---|---|---|---|---|
| 정부·공공 | 66 | 49 | 2 | 15 | 1,478 |
| 학교 | 356 | 226 | 14 | 116 | 7,383 |
학교만 갈래별로 보면 장학 957건(148곳) · 학사 668건(141곳) · 입학 410건(122곳) · 채용 1,572건(169곳) ·
공지 1,432건(159곳)입니다. 같은 날 오전, 갈래 게시판 찾기 전의 점검은 학교
146곳 3,552건, 장학 406건(72곳)이었고, 다섯 갈래(공지·학사·장학·입학·채용)에 모두 글이 나온 학교는
13곳에서 58곳이 됐습니다. 경희사이버대처럼 서버가 느린 곳은 점검마다 글이 나왔다 안 나왔다
합니다(robots.txt 를 시간 안에 못 받으면 수집하지 않으므로). 한국외대는 확인된 게시판 번호를
프리셋으로 넣어 두었다(공지·학사·장학·채용·학술 + 학생지원팀 장학·학생활동 —
examples/sources-schools.json).
목록에서 제목과 글 주소를 고르는 차례는 ① 글 링크 ② 스크립트로만 열리는 제목(주소는 같은
행의 문서 보기·첨부, 없으면 목록) ③ 첨부 파일 이름 ④ 링크가 '자세히보기'·'다운로드' 단추뿐인
행의 제목 글입니다. 파일 이름이 제목보다 길어 제목 자리를 빼앗거나(금융위·해수부·성균관대),
제목 링크 안에 숨은 휴대폰용 꼬리('… 학생지원팀 2026-10-08 157')가 붙던 것을 이렇게 바로잡았습니다.
어느 게시판이 왜 0건인지는 /api/verify?stage=rows&ids=<기관> 으로 칸 모양(칸 글자 앞 40자·주소)과
고른 제목을 보면 원문 HTML 없이 가려집니다(robots.txt 가 막은 주소는 열지 않음).
글의 갈래는 게시판 이름이 먼저, 그다음 글 제목으로 정합니다. '장학공지' 게시판의 글은 전부 장학이고, '공지사항'에 올라온 '○○재단 장학생 모집'도 제목으로 장학이 됩니다. 게시판 이름을 모를 때('READ'·'더보기')만 글 제목들을 보고 게시판 이름을 짓습니다(60% 이상이 한 갈래일 때) — 이름 있는 게시판까지 내용으로 바꿨더니 일반 공지가 '입학안내'·'장학'이 되는 오분류가 생겨서 그렇게 정했습니다.
못 모은 학교 116곳은 robots.txt 로 수집을 막은 곳(38, 설계상 따름), 점검 60초 안에 게시판을 다 못 본 곳(27), 게시판·홈이 자바스크립트로만 그려지는 곳(23), 해외 클라우드 망 접속을 받지 않는 곳(10), 인증서가 잘못된 곳(5, 검증을 끄지 않음) 등입니다. 실제 화면은 기관당 240초까지 찾으므로 '시간 안에 다 보지 못함'으로 남은 곳은 휴대폰에서 직접 모을 때 잡히기도 합니다.
홈 첫 화면의 메뉴만 보면 학교 대부분이 '공지사항' 하나만 걸립니다(오전 캐시: 학교 164곳 중
장학 게시판이 있는 곳 50, 다섯 갈래를 다 가진 곳 7). 장학·학사 게시판은 대개 '대학생활 > 장학 >
장학공지'처럼 한두 단계 안쪽이나 따로 떨어진 사이트(입학처·학생지원)에 있습니다. 한국외대처럼
사람이 게시판 번호를 찾던 순서를 그대로 코드로 옮겼습니다(slots.py):
artclList.do 등)를 시험학생이 묻는 게시판(문의·상담·Q&A)·후기, 학사일정·행사 달력·식단, 분실물·자취방, 학과 게시판, 로그인 시스템은 후보에서 뺍니다. 날짜 줄이 2~4줄뿐인 목록('학과별 취업률'·'입학·교육')은 이름이 게시판다울 때만 다른 후보가 없을 때의 대안으로 씁니다.
전 학교를 돌려 보며 함께 고친 것:
subview.do)을 'view.do 로 끝난다'는 이유로 글 한 건으로 보고 통째로 빼던 것
(subview.do?enc=… 는 enc 안쪽이 artclView 일 때만 글)index.do?MENU_ID=…·/main/163 꼴인 학교의 게시판을 '첫 화면'으로 보고 빼던 것manifest.json 으로 끌려가던 관문, 호스트 이름으로 설정 JSON 을
불러 옮겨 가는 관문(한라대), 도메인을 옮긴 학교(충북대 → cbnu.ac.kr), 'site move' 만 남은 홈
('/{사이트}/index.do' 진입점)발견을 두 번(/api/verify?stage=discover — 무엇을 열고 골랐는지 trace 로 돌려준다) 돌려 예전
캐시와 합친 뒤 수집 점검으로 확인해 구웠습니다: 게시판을 아는 학교 164 → 246곳, 캐시 기준으로
장학 게시판이 있는 학교 50 → 127곳, 학사 50 → 134곳, 입학 60 → 158곳, 채용 51 → 162곳,
다섯 갈래를 다 가진 학교 7 → 67곳.
서버는 글 화면에서 그림·첨부 파일의 주소와 표 개수만 찾아 돌려줍니다(본문 글자는 가져오지 않는다는 원칙 그대로). 그림은 휴대폰 브라우저가 원래 사이트에서 직접 받고, 이 앱은 아무것도 저장하지 않습니다.
.ac.kr·.go.kr·.re.kr) 밖의 그림·첨부(책 표지·기사 사진·문의 게시판의
광고)는 불러오지 않고 개수만 알립니다실측(2026-10-11, 배포 서버) — 글이 있는 194곳에서 기관마다 서로 다른 게시판의 최근 글을 최대 3건씩, 모두 425건을 열어 보았습니다.
| 항목 | 결과 |
|---|---|
| 단추가 붙은 글 | 316건(74%) — 이 가운데 309건이 열림(나머지는 robots.txt·서버 오류·시간 초과) |
| 단추 없음 | 109건 — 글마다 주소가 없는 게시판 94 · 목록 밖 사이트(언론 기사) 9 · 글이 곧 파일 6 |
| 그림 | 92건에서 170장 |
| 첨부 | 131건에서 300개(HWP 87 · PDF 80 · 바로보기 63 · 그림 파일 48 · XLS 8 · ZIP 5 …) |
| 표 | 47건에서 62개(넓은 표 14건 — '데스크톱 사이트' 안내) |
| 글 제목을 화면에서 찾음 | 289 / 309건(94%) — 못 찾으면 사이트 껍데기를 더 엄격히 거른다 |
| 다른 사이트 그림·첨부 | 그림 12 · 첨부 1 — 개수만 알림 |
open_site_clipper --web # http://127.0.0.1:8765 — 배포본과 같은 화면
open_site_clipper --web --lan # 같은 와이파이의 휴대폰에서 http://<PC 주소>:8765
public/ 화면(HTML·CSS·JS, 의존성 없음) + 홈 화면 아이콘
api/catalog.py 기관 목록 ┐ 전부 src/open_site_clipper/webapp.py 를 부른다
api/collect.py 기관 하나 수집 │ (로컬 --web 도 같은 함수)
api/verify.py 여러 기관 일괄 점검 │
api/media.py 글 한 건의 그림·첨부 주소 ┘
examples/sources-gov.json · sources-schools.json 기관·학교 목록(홈 주소만)
examples/sources-*.json 에 이름과 홈 주소 한 줄이면 됩니다# 네트워크 없이 번들 샘플로 동작 확인 (HTML 보고서)
open_site_clipper --demo -o demo.html
# 실시간 수집 → 마크다운 파일
open_site_clipper --format markdown -o report.md
# 최근 7일 · 특정 기관만
open_site_clipper --since 7 --agency 행정안전부 -o mois.html
# 설정된 출처 확인
open_site_clipper --list-sources
# 이전 실행 대비 신규 공지만 (첫 실행은 기준선 저장)
open_site_clipper --state state.json --only-new -o new.html
# 사내 회람 서식으로 출력
open_site_clipper --template examples/circular-template.tmpl -o circular.md
# 테마 브리프 — 관련 자료만 골라 섹션·해석까지
open_site_clipper --theme examples/theme-data-digital.json -o brief.html
# 한국외대 전 사이트를 한 기관으로 — 기관→사이트→부서 보고서
open_site_clipper --sources examples/sources-hufs.json --group-by org -o hufs.html
# 목적으로 검색 — '고용' 한 마디가 채용·모집·공채·인턴으로 확장
open_site_clipper --sources examples/sources-hufs.json --query 고용 -o 고용.html
--demo --format markdown)# 정부·공공기관 공지 보고서
- 생성 시각: 2025-07-07T09:00:00+09:00
- 공지 5건 · 기관 2곳
## 기간 요약
- 기관: 행정안전부 3건 · 과학기술정보통신부 2건
- 분류: 보도자료 5건
## 행정안전부 (3건)
| 발행일 | 제목 | 등급 |
|---|---|---|
| 2025-07-07 | [재난안전데이터 공유 플랫폼 정식 개통](https://www.mois.go.kr/notice/1001) | KOGL-1 |
| 2025-07-04 | [여름철 집중호우 대비 국민행동요령 안내](https://www.mois.go.kr/notice/1002) | KOGL-1 |
...
### 출처 및 재이용 조건
- **KOGL-1** — 공공누리 제1유형 — 출처표시(상업적 이용·변형 허용)
실제 렌더링 결과는 examples/ 폴더를 참고하세요 — 공지 보고서 demo-report.html · .md · .json, 테마 브리프 demo-brief.html · .md.
단위 테스트 265개(전부 오프라인, 페처 주입)에 더해 실제 사이트에서 끝까지 확인했습니다.
한국외국어대학교 실수집 — K2Web 사이트 프리셋으로 한 번에 공지 88건, 기관→사이트→부서 3단 보고서. 목록의 작성자 칸에서 행정지원처·전략기획팀· 장학팀 같은 실제 부서명이 그대로 추출됩니다.
폴백 실동작 — hufs.ac.kr 의 robots.txt 는 /bbs/* 를 차단합니다. RSS·목록이
막히자 캐스케이드가 다음 수단으로 넘어가 수집했고, 그 이력이 보고서에 그대로
남습니다(조용한 실패 금지):
rss: robots.txt 차단 → list: robots.txt 차단 → page: 60건
타 대학 호환 — 한국방송통신대학교 게시판이 같은 CMS(K2Web Wizard)·같은 칸 구조임을 확인. 좌표만 바꾸면 코드 수정 없이 동작하며, 고려대·전북대 등도 같은 CMS 를 씁니다.
정부기관 65곳 실수집 — 부·청·위원회를 한 번에 돌려 공지 3,600여 건 · 기관 37곳을 모았습니다. 분류는 보도자료·공지·채용·입찰·소식·인사·업무추진비 등으로 갈립니다. 실패한 기관은 사유가 남습니다:
⚠ 외교부 보도자료 (korea: 주소 없음(404))
⚠ 해양수산부: 진단: 응답 0KB · <a> 0개 · 내부 0 · 후보 0개
수집을 거듭하며 드러난 실제 문제들 — 한글 날짜 표기(2026년 7월 20일)를
못 읽던 것, 첨부 칸이 제목 자리를 빼앗던 것, 후보 40개 상한에 소개 메뉴만
차던 것 — 을 하나씩 고쳐 왔습니다. 지금도 홈이 빈 응답인 기관 19곳은 원인을
좁히는 중이며, 진단 숫자가 보고서에 그대로 남습니다.
open_site_clipper [옵션]
-f, --format {md,markdown,html,json} 보고서 형식 (기본: html)
-o, --output FILE 출력 파일 (기본: 표준 출력)
--since DAYS 최근 N일 이내 공지만
--agency NAME 기관명 부분일치 필터
--sources FILE 사용자 정의 출처 JSON
--input DIR 오프라인 모드(저장한 피드 디렉터리)
--demo 번들 샘플로 오프라인 보고서
--state FILE 실행 간 상태(JSON) — 신규 공지 🆕 표기·저장
--only-new 신규 공지만(--state 필수)
--digest / --no-digest 기간 요약(기관·분류·키워드) 포함 여부 (기본: 포함)
--template FILE 사용자 템플릿 출력(지정 시 --format 무시)
--query TERMS 목적·키워드 즉석 검색(동의어 확장, --theme 배타)
--theme FILE 테마 브리프 — 관련 자료만 선별·섹션화·해석
--min-score N 테마 관련성 채택 하한 (기본 3)
--group-by agency|topic|org 섹션 축 — org 는 기관→사이트→부서 (기본 agency)
--quote-mode conservative|full 발췌 정책 — full 은 등급 미상(대학 공지)도 발췌 유지
--deep-links 본문에서 첨부·관련 자료 링크 수집
--deep-links-limit N 본문을 열어볼 공지 수 상한 (기본 20)
--list-sources 설정된 출처 출력
--title TEXT 보고서 제목 재정의
--discover URL 홈페이지 주소로 출처 초안 자동 탐지
--discover-org URL 조직 산하 여러 사이트까지 훑어 초안 생성
--max-sites N --discover-org 가 훑을 사이트 수 (기본 6)
--check-access FILE 수집 전 접근 진단(robots 판정만, 수집 안 함)
--jobs N 동시에 처리할 기관 수 (기본 16)
--delay SEC 같은 서버 요청 간격 (기본 1.0, robots 우선)
--serve 로컬 웹 UI 시작(브라우저 자동 오픈)
--port N --serve 포트 (기본 8765)
공공데이터포털(kind: "datago") 출처는 data.go.kr에서
발급받은 인증키가 필요합니다. 키는 저장소·출처 파일에 적지 말고 환경변수로만
넘기세요.
export OSC_DATAGO_KEY="발급받은-serviceKey" # 인코딩/디코딩 키 모두 가능
open_site_clipper --sources my.json -o report.html
URL에 serviceKey를 직접 쓴 경우 그 값을 존중하며, 형식 파라미터(type 등)가
없으면 type=json을 붙입니다(파서는 JSON만 읽음). 키가 없으면 해당 출처는
네트워크를 두드리지 않고 보고서 표지에 "인증키 미설정" 으로 구분 표기됩니다.
--state)--state FILE을 주면 이전 실행에서 본 공지 목록(JSON)을 기억해, 이번에 처음
등장한 공지를 🆕(MD)·NEW 배지(HTML)·"new": true(JSON)로 표기하고 실행 후
상태를 갱신합니다. 파일이 없으면 첫 실행(기준선) 으로 간주해 아무것도 신규
표기하지 않습니다 — 첫 보고서 전체가 🆕로 도배되는 오탐을 막습니다.
--only-new는 신규 공지만으로 보고서를 만듭니다(크론 알림용).
--digest)보고서 상단에 기관별 건수·분류 분포·제목 키워드 상위를 붙입니다. 모델·외부
API 없이 순수 빈도 집계라 같은 입력이면 항상 같은 요약이 나옵니다(재현 가능).
상투어(안내·공고 등)·숫자·회차·기관명은 키워드에서 제외합니다. 끄려면
--no-digest.
--query)테마 파일 없이 목적어 한 마디로 검색합니다. 목적 사전에 있는 말은 동의어로
자동 확장되고, 없는 말(예: AI, 반도체)은 그 말 자체가 키워드가 됩니다.
여러 개를 나열하면 각각이 브리프의 [섹션]이 됩니다.
open_site_clipper --sources knou.json --query 고용 -o 고용.html
open_site_clipper --sources knou.json --query "고용 장학" --state s.json --only-new
| 목적어 | 자동 확장되는 동의어 |
|---|---|
고용 | 채용 · 모집 · 공채 · 임용 · 인턴 · 일자리 · 취업 · 구인 · 신입 · 경력 |
복지 | 장학 · 지원금 · 학자금 · 생활비 · 기숙사 · 상담 · 의료 · 건강 · 보험 · 돌봄 |
안전 | 재난 · 화재 · 지진 · 호우 · 안전점검 · 행동요령 · 대피 |
입찰 | 공고 · 낙찰 · 계약 · 조달 · 발주 · 제안요청 · RFP |
장학 | 장학금 · 학자금 · 등록금 · 면제 · 감면 · 국가장학 |
정부투자 | 공모 · 지원사업 · 국고 · 연구비 · R&D · 과제 · 예산 · 출연 · 보조금 · 투자 |
학사 | 수강 · 성적 · 졸업 · 등록 · 휴학 · 복학 · 계절학기 · 시험 · 학점 |
행사 | 세미나 · 특강 · 설명회 · 박람회 · 포럼 · 축제 · 경진대회 · 공모전 · 워크숍 |
확장 근거는 항목마다 근거 키워드로 표기되어 왜 뽑혔는지 검증할 수 있습니다.
동의어 사전은 규칙 기반(무LLM)이며 purposes.py에서 수정·추가할 수 있습니다.
한국어 처리에 관하여 — 형태소 분석기 pynori(KoreanTokenizer)를 코드 수준에서 분석했습니다. 격자 탐색·TRIE 최장일치의 품질 원천은 93MB mecab-ko-dic 사전이었고, 스타순 상위 대안(soynlp·Kiwi·KoNLPy)도 대사전· 말뭉치·네이티브 코드를 요구합니다. 의존성 0 원칙에 따라 원리만 증류해, 닫힌 품사(다문자 조사·어미) 최장일치 정규화기(
korean.py)로 축소 구현했습니다 — "지원하는/지원하며"가 집계에서 "지원"으로 합쳐집니다. 관련성 매칭 자체는 부분 문자열이라 "채용을·모집합니다"도 원래 잡힙니다.
--serve)cmd 가 불편하면 브라우저로 씁니다.
open_site_clipper --serve # http://127.0.0.1:8765 자동 오픈, 종료는 Ctrl+C
수집이 도는 동안에는 진행 화면이 뜹니다 — 왼쪽에 진행 막대·몇 곳 중 몇 곳· 모은 공지 수·걸린 시간·남은 예상, 오른쪽에 지금 어느 기관의 어느 주소를 두드리는지가 실시간으로 보입니다(병렬이라 여러 줄이 동시에 뜹니다). 끝나면 보고서로 자동으로 넘어갑니다.
화면에서 ① 조사할 조직 선택 — 정부·공공기관 / 대학 / 기타 그룹으로 묶여
접이식으로 나오고, 그룹마다 [모두 선택] [모두 해제] 가 있습니다. 체크한
기관만 조사합니다. 같은 기관이 여러 파일에 흩어져 있어도 한 줄로 합쳐집니다 →
② 옵션(기관→사이트→부서 묶기 · 발췌 유지 · 신규 🆕 · 최근 N일) → ③ 검색어
(넣으면 목적 브리프, 비우면 전체 보고서) → [보고서 만들기]. ④ 조직 추가에
대학 주소를 넣으면 --discover 가 돌아 초안을 저장하고 곧바로 ①의 목록에
나타나며, [이 조직으로 바로 보고서] 원클릭도 됩니다.
CLI와 같은 계층을 부르는 얇은 껍데기라 의존성은 그대로 0(표준
http.server)이고, 127.0.0.1에만 바인딩되어 이 컴퓨터에서만 접속됩니다 —
개인용 로컬 도구이며 인터넷 배포용이 아닙니다. 수집은 실제 요청이라 수십 초
걸릴 수 있습니다.
kind: "k2web")한국외국어대학교처럼 본부·처·팀·대학원·연구소가 홈페이지를 따로 운영해도,
같은 CMS(K2Web Wizard)를 쓰므로 좌표만 주면 한 기관으로 묶어 수집합니다.
좌표는 URL 세 조각입니다: host(도메인), site_id(경로의 사이트 코드),
board_id(게시판 번호 — 게시판 목록 주소 /bbs/{site_id}/{board_id}/artclList.do에서 확인).
{
"org": "한국외국어대학교", "site": "대학본부",
"name": "한국외국어대학교 대학본부", "kind": "k2web",
"host": "www.hufs.ac.kr", "site_id": "hufs",
"board_id": 2180, "menu_no": 11281, "category": "공지"
}
수집은 네 수단을 순서대로 시도하고, 앞이 막혀도 멈추지 않습니다.
| 순위 | 수단 | 주소 | 특징 |
|---|---|---|---|
| 1 | rss | /bbs/{site}/{board}/rssList.do?row=50 | 구조화·발췌 포함 |
| 2 | list | /bbs/{site}/{board}/artclList.do | 목록 표 — 작성 부서를 줌 |
| 3 | api | 출처에 설정한 JSON API (선택) | 응답 골격을 경로로 지정 |
| 4 | page | /{site_id}/{menu_no}/subview.do | /bbs/가 막혀도 사는 경로 |
다음 수단으로 넘어가는 조건은 셋입니다 — robots.txt 차단 · 응답 없음 · 파싱 0건.
robots 판정은 표준 urllib.robotparser로 실행 시점에 우리 User-Agent 기준으로
묻고(무시 옵션은 없음), 전부 실패하면 보고서 표지에 시도 이력이 그대로 남습니다:
⚠ 수집 실패 출처: 대학본부 (rss: robots.txt 차단 → list: 응답 없음 → api: 글 0건 → page: 응답 없음)
3순위 JSON API는 사이트가 게시판 JSON을 줄 때만 설정합니다. 코드가 아니라 점 표기 경로로 응답 골격을 가리킵니다:
"api_url": "https://www.hufs.ac.kr/…/board.do?bbsId=2180",
"api_paths": {
"items": "data.list", "title": "artclNm",
"url": "artclUrl", "article_no": "artclNo",
"date": "regDt", "unit": "deptNm"
}
url이 없으면 article_no(글번호)로 정식 글 주소를 조립합니다. 대학·교내
공지처럼 공공누리 표기 관행이 없는 곳은 등급이 전부 '미상'이라 기본 인용
정책이 발췌를 비우므로, --quote-mode full을 함께 쓰면 발췌가 유지됩니다.
결과 보고서는
--group-by org로 기관 → 사이트 → 부서 3단으로 봅니다. 실측 좌표가 담긴
프리셋은 examples/sources-hufs.json.
--discover)새 대학·기관을 추가할 때 좌표를 손으로 캐는 대신, 홈페이지 주소 하나를 줍니다.
open_site_clipper --discover https://www.knou.ac.kr/knou/index.do -o knou.json
# 탐지 완료: 후보 4건(검증 4건) · 요청 5회 · 기관명 추정 '한국방송통신대학교'
무엇을 찾는지 — ① 표준 RSS 자동발견(<link rel="alternate">), ② K2Web 좌표
(페이지에 노출된 artclList/rssList 링크 + '공지·소식'류 메뉴를 예산 내에서 한
단계만 따라가 게시판 번호를 캐냄), ③ 둘 다 없으면 관용 경로(/rss, /feed 등)
추측. 후보마다 실제로 받아 RSS 여부를 스니핑해 _verified로 표시하고, 어디서
찾았는지 _evidence에 남깁니다.
결과는 초안입니다 — 그대로 --sources로 읽히지만, org·name을 다듬고
_verified: false 항목은 직접 확인하는 것을 전제합니다. robots.txt를 지키고 총
요청 수에 예산(기본 12회)을 두며, JS로만 그리는 메뉴나 비지원 CMS는 못 찾을 수
있습니다(그 경우 게시판 페이지 주소를 직접 --discover에 주면 됩니다).
피드 목록 페이지도 읽습니다. 정부 사이트는 "RSS 서비스"·"정보구독서비스" 페이지에 피드 주소를 표로 모아 둡니다. 그 주소를 주면 표를 읽어 항목마다 출처를 만듭니다 — 기관·메뉴 이름은 앵커 텍스트("RSS복사")가 아니라 같은 행의 첫 칸에서 가져옵니다.
# 정부 전체 부처 피드 목록 한 장에서
open_site_clipper --discover https://www.korea.kr/etc/rss.do -o gov.json
# 개별 부처의 공지·인사·보도자료 피드
open_site_clipper --discover https://www.mcst.go.kr/site/s_etc/rss/rssService.jsp -o mcst.json
부처 링크는 개편으로 바뀌지만 이 목록 페이지는 정부가 갱신하므로, 주소를 코드에 박아 두지 않아도 그 시점의 목록을 그대로 얻습니다. 부처가 RSS 로 내주지 않는 메뉴(예: 일부 부처의 채용·입찰)는 이 방법으로도 나오지 않습니다.
설계 출처: autoscraper('예시 하나→재사용 규칙' — K2Web에선 URL 문법이 곧 규칙), feed_seeker(탐지 3원·제한 따라가기), feedfinder(후보·검증 분리). 셋 다 requests·bs4 의존이라 원리만 표준 라이브러리로 이식했습니다.
메뉴 이름으로는 판정할 수 없습니다. 같은 정보공개 가 어떤 기관에선 날짜
붙은 목록이고 어떤 기관에선 설명문 한 장입니다. 그래서 페이지를 열어 모양을
봅니다.
| 판정 | 예시 | 처리 |
|---|---|---|
| 목록 (날짜 붙은 글 2건 이상) | 공지사항·인사알림·채용·입찰·보도설명 | ✅ 수집 |
| 안내 페이지 (글 0~1건) | 일반현황·교육지원한눈에 | 건너뜀 |
| 링크 모음 (날짜 없음) | 정책 대분류 메뉴 | 건너뜀 |
| 기관 밖 도메인 | 법령정보(law.go.kr)·공공데이터·국민신문고 | 별도 출처로 등록 |
게시판을 못 찾으면 그 이유를 숫자로 남깁니다 — 응답 248KB · <a> 0개 (주소없음 0·data속성 0) · 내부 0·외부제외 0 · 후보 0개. 메뉴가 JavaScript 로만
그려지는지, 파서가 막혔는지, 주소가 data-* 에 숨어 있는지가 한 줄로 드러납니다.
홈을 못 읽어도 거기서 멈추지 않습니다 — 알려진 경로 패턴(CMS 패밀리 8종)을
사이클로 시도해 게시판을 찾습니다. 첫 경로가 통한 패밀리만 깊게 파므로 요청이
적게 듭니다. 새 패턴은 data/gov-paths.json 에만 추가하면 되고 코드는 그대로입니다.
그런 사이트는 robots.txt 의 Sitemap: 을 읽어(추가 요청 없이) 사이트맵에서
목록 주소를 찾아 우회합니다.
건너뛴 것은 사유와 함께 보고서에 남습니다. 실패는 뭉뚱그리지 않고 원인을
구분합니다 — 접근 거부(403) · 주소 없음(404) · 시간 초과(15초) · 요청 과다(429).
일시적으로 보이는 실패는 한 번 재시도합니다.
수집된 항목마다 어디서 가져왔는지가 제목 아래 작은 상자로 붙습니다
(www.korea.kr · korea.kr 피드 · /rss/dept_mcst.xml,
www.mcst.go.kr · 게시판 · /kor/s_notice/notice/noticeList.jsp) — 어느 게시판인지까지. 같은 기관이라도
항목마다 경로가 다를 수 있어, 출처를 눈으로 확인할 수 있게 남깁니다. 기본으로 최근 2년(--since 730)
자료만 가져오며, 발행일을 알 수 없는 항목은 버리지 않고 포함합니다. 이 규칙
하나로 업무계획 같은 문서 저장소가 정리됩니다 — 최근 것만 남습니다.
--jobs --delay)open_site_clipper --sources examples/sources-gov.json --jobs 16 --delay 1.0 -o gov.html
기관은 동시에, 한 서버에는 천천히 보냅니다. 기관마다 서버가 다르므로 동시에 보내도 어느 한 서버에 몰리지 않고, 같은 서버로 가는 요청 사이에는 최소 간격을 지킵니다. 그 간격은 사이트가 정합니다:
robots.txt 에 Crawl-delay: 5 가 있으면 → 5초를 지킴
없으면 → --delay 값(기본 1.0초)
숫자를 우리가 정하기 전에 상대에게 먼저 묻는 방식입니다. 65곳 순차 수집이
16분 걸리던 것이 병렬로는 몇 분 안쪽으로 줄어듭니다(--jobs 1 이면 순차).
examples/sources-gov.json 에 부(29)·청(18)·위원회(7)·대통령 소속 위원회(11)
65곳이 들어 있습니다. 담긴 것은 홈 주소와 korea.kr 피드 코드뿐이고,
게시판 경로는 실행할 때 찾습니다.
open_site_clipper --check-access examples/sources-gov.json # 먼저 진단
open_site_clipper --sources examples/sources-gov.json --agency 문화체육 -o mcst.html
기관마다 홈페이지를 한 장 읽어 앵커 텍스트로 카테고리를 판정합니다 —
채용정보→채용, 입찰공고→입찰, 알립니다→공지, 인사발령→인사. 그리고
같은 카테고리에 후보 주소를 여러 개 모읍니다. 하나가 robots 로 막혀도
캐스케이드가 다음 후보로 넘어갑니다. RSS 서비스 링크가 있으면 한 단계
따라가 피드 목록 표까지 읽습니다.
CMS 를 가리지 않습니다. 정부 사이트는 CMS 가 최소 19종으로 갈리지만, 링크 문법이 아니라 앵커 텍스트와 표 구조에 기대므로 같은 코드가 돕니다.
⚠ 65곳을 한 번에 돌리면 요청이 수백 회입니다.
--check-access로 먼저 진단하고,--agency나 웹 UI 로 필요한 기관만 고르세요.
파일에 rights 를 일부러 비워 두었습니다 — 정부 자료라고 전부 공공누리
1유형이 아닙니다(4유형 실측). 미상이면 제목·링크·날짜·부서는 수집되고 발췌만
비워집니다.
examples/sources-schools.json 에 4년제(187)·교육대(10)·과학기술원(4)·특수대(7)·
방송통신대(1)·사이버대(22)·전문대(123)·전공대학(2)이 홈 주소만 들어 있습니다.
정부 65곳과 같은 방식으로 실행 시 게시판을 찾되, 학교는 공지·학사·장학·입학·채용 게시판을
갈래마다 하나씩 찾아 채웁니다(학교 갈래 게시판 찾기). 학교 게시판은
입학·장학·학사 갈래로 따로 분류됩니다(‘신입생 모집’이 채용으로 빠지지 않게).
open_site_clipper --sources examples/sources-schools.json --agency 한국외국어 -o hufs.html
목록은 2026-10 웹 검색으로 통합·폐교·교명 변경을 반영했습니다(강릉원주대→강원대,
원광보건대→원광대, 전남도립대→국립목포대, 거창·남해대→국립창원대 통합, 광양보건대 폐교,
KC대→강서대 등). 대학원대학은 아직 넣지 않았습니다. 웹 화면은 type·region 으로
유형·지역 거르기를 만듭니다.
--check-access)정부 사이트는 robots.txt 로 막힌 곳이 많은데, 막힌 방식이 두 가지입니다. 수집을 돌리기 전에 어느 쪽인지 확인합니다.
open_site_clipper --check-access examples/sources-gov.json
기관 허용/전체 결론
교육부 1/7 ◐ 일부 허용 — 열린 경로로 수집
✗ 공지/board: https://www.moe.go.kr/boardCnts/listRenew.do?…
문화체육관광부 16/16 ✓ 전 경로 허용
외교부 1/1 — 자체 경로 미설정 — 보도자료만
행정안전부 4/4 ✓ 전 경로 허용
요약: 기관 4곳 — 전 경로 허용 2 · 자체 경로 미설정 1 · 일부 허용 1
※ robots.txt 는 User-Agent 별로 규칙이 다릅니다. 위 판정은 이 도구 기준입니다.
Disallow: /)이면 어떤 주소를 찾아도 소용없습니다 → korea.kr·
data.go.kr 경로만 남습니다.alt 단계가 값을 합니다.두 번째 줄이 중요한 이유는, 남이 다른 도구로 잰 차단 목록이 우리에게 그대로 적용되지 않기 때문입니다. robots.txt 는 User-Agent 별로 규칙이 갈리므로 이 도구의 UA 로 직접 물어야 합니다. 진단은 수집을 하지 않고 robots.txt 만 읽습니다(호스트당 1회, 캐시).
kind: "govorg")정부는 부처마다 CMS가 달라(실측 19종) 대학처럼 좌표로 주소를 만들 수 없고, robots.txt가 경로를 막는 곳도 많습니다. 그래서 메뉴 종류(보도자료·공지·인사· 채용·입찰)마다 아래 순서로 시도하고, 앞이 막히면 다음으로 넘어갑니다.
| 순위 | 단계 | robots | 얻는 것 |
|---|---|---|---|
| 1 | rss | 검사 | 기관 자체 피드 |
| 2 | board | 검사 | 기관 게시판 표 |
| 3 | alt | 검사 | 같은 목록의 다른 주소 |
| 4 | datago | 무관 | 공공데이터포털 API |
| 5 | korea | 무관 | korea.kr 부처 피드(보도자료 안전망) |
{ "org": "문화체육관광부", "kind": "govorg", "korea_feed": "dept_mcst",
"routes": [["공지", "rss", "https://www.mcst.go.kr/common/rss/notice.jsp"],
["채용", "board", "https://www.mcst.go.kr/site/s_notice/notice/jobList.jsp"]] }
대학 캐스케이드와 결정적으로 다른 점: 대학은 4단계가 같은 글로 가는 다른 길이라 첫 성공에서 멈췄지만, 정부는 단계마다 주는 것이 달라 카테고리별로 따로 폴백합니다. 보도자료가 korea.kr로 성공해도 채용 게시판은 따로 시도합니다.
alt는 우회가 아닙니다. robots가 막은 주소 대신 같은 내용을 담은 다른 주소
(모바일 도메인·www 유무·영문판 경로)를 만들어 robots 판정을 다시 받는 것이고,
거기서도 막히면 그대로 건너뜁니다. 어느 기관에서 통할지는 미지수라 되면 쓰고
안 되면 사유가 남습니다:
⚠ 외교부 공지 (board: robots.txt 차단 → alt: robots.txt 차단 → alt: robots.txt 차단)
※ 같은 기관의 보도자료는 korea.kr 경로로 수집됨
kind: "govweb")부처는 공지·인사·보도자료·언론설명을 RSS 로 공개합니다(각 사이트의
"정보구독서비스" 페이지). 반면 채용·입찰은 RSS 가 없는 경우가 많아
목록 페이지를 직접 읽어야 합니다 — 그때 kind: "govweb" 을 씁니다.
좌표가 필요 없고 목록 주소만 적으면 됩니다.
{ "org": "문화체육관광부", "name": "문화체육관광부", "kind": "govweb",
"url": "https://www.mcst.go.kr/site/s_notice/notice/jobList.jsp",
"category": "채용", "rights": "kogl_type1" }
# RSS 4종 + 채용·입찰 2종을 한 기관으로
open_site_clipper --sources examples/sources-mcst.json --group-by org -o mcst.html
# 목적으로 좁혀 보기
open_site_clipper --sources examples/sources-mcst.json --query 채용 -o 채용.html
파서는 상세 링크 문법에 의존하지 않습니다. 이 게시판들은 소속·공공기관
공고를 각 기관 누리집과 연동해 보여주기 때문에 링크가 제각각입니다. 대신 표의
칸 순서(번호→제목→게시일→마감일→조회)에 기대어, 행에서 실제 링크를 단 가장 긴
텍스트 칸을 제목으로, 그 뒤 첫 날짜를 게시일로 읽습니다. 제목 앞 [기관명]
접두는 부서로 뽑습니다.
한계: 목록이 표가 아니거나 JavaScript 로만 그려지는 게시판은 읽지 못합니다.
부처마다 RSS 제공 범위가 달라, 있는 것은 RSS 로 없는 것만 govweb 으로 채우는
방식이 안전합니다.
--theme)수집한 공지 전부를 나열하는 대신, 테마에 관련된 자료만 골라 섹션 브리핑을 만듭니다. 관련성 판정은 키워드 규칙(무LLM)이라 같은 입력이면 같은 결과가 나오고, 채택 근거 키워드와 점수를 항목마다 표기하므로 왜 이 자료가 실렸는지 검증할 수 있습니다.
open_site_clipper --theme examples/theme-data-digital.json -o brief.html
open_site_clipper --theme my-theme.json --min-score 5 --only-new --state s.json
테마 파일:
{
"name": "우주",
"description": "발사체·위성 동향",
"keywords": { "우주": ["space", "항공우주"] },
"sections": [
{ "name": "발사체", "keywords": { "발사체": ["로켓"], "재사용": [] } },
{ "name": "위성", "keywords": { "위성": ["satellite", "군집위성"] } }
],
"glossary": { "LEO": "지구 저궤도 — 고도 2,000km 이하" }
}
keywords의 키가 정준 키워드, 값 배열이 동의어(영문 표기 포함).--min-score로 조절합니다.sections가 브리프의 묶음·순서이고, 어디에도 안 맞으면 기타로 갑니다.glossary는 보고서 옆 용어 각주로 렌더됩니다.브리프에는 계산으로 얻은 해석이 함께 붙습니다 — 서술이 아니라 수치입니다.
--state 사용 시 이번에 새로 등장한 키워드그래프는 표준 라이브러리만으로 조립한 인라인 SVG라 HTML 파일 하나로 자체 완결되며(외부 요청 0), 같은 입력이면 같은 그림이 나옵니다.
topics) 과 --group-by출처마다 주로 다루는 주제를 태그로 달아 두면(topics), 관련성 판정의 가점과
주제별 섹션화에 쓰입니다.
{ "name": "과학기술정보통신부", "kind": "rss", "url": "...", "topics": ["과학기술", "정보보호"] }
--group-by topic을 주면 기관 대신 주제별로 묶은 보고서가 나옵니다.
--deep-links)공지 본문 페이지를 열어 첨부·관련 자료 링크만 캐옵니다(보도자료 PDF, 설명자료
HWP 등). 본문 텍스트는 가져오지 않습니다 — 원문 복제를 하지 않는다는 원칙과
등급별 보수적 인용 정책을 그대로 지키며, 변형이 금지된 등급(3·4유형·미상)은
링크 수집도 건너뜁니다. 공지마다 요청이 늘어 느려지므로 기본은 꺼짐이고
--deep-links-limit(기본 20건)로 상한을 둡니다.
--template)조직 서식(회람·공문 틀)에 수집 결과만 끼워 넣고 싶을 때 씁니다. 표준
string.Template 문법으로, 템플릿 속 $마커가 치환됩니다($$는 $로,
모르는 마커는 원문 유지). 예시는 examples/circular-template.tmpl.
| 마커 | 내용 |
|---|---|
$title $generated_at | 제목 · 생성 시각 |
$count $agency_count $new_count | 공지·기관·신규 건수 |
$agencies $failed_sources $since_days | 기관 목록 · 실패 출처 · 조회 기간 |
$body_md $digest_md $legend_md | 본문 표·기간 요약·범례 (Markdown) |
$body_html $digest_html $legend_html | 위와 동일 (HTML 조각) |
--sources my.json으로 원하는 기관 피드를 넣을 수 있습니다.
{
"sources": [
{ "name": "서울특별시", "kind": "rss",
"url": "https://example.seoul.go.kr/rss", "rights": "kogl_type1" },
{ "name": "공공데이터포털", "kind": "datago",
"url": "https://apis.data.go.kr/....", "rights": "kogl_type1" }
]
}
kind는 rss(RSS/Atom) 또는 datago(data.go.kr OpenAPI, JSON), rights는
public_domain · kogl_type1~kogl_type4 · unknown 중 하나입니다.
인터넷이 막힌 환경(대회 심사·에어갭)이나 결과를 고정하고 싶을 때, 피드를
<source-id>.xml 형태로 저장해 두고 --input으로 읽습니다.
open_site_clipper --input ./saved_feeds --format html -o report.html
| 배지 | 등급 | 재이용 조건 |
|---|---|---|
제7조 | 저작권법 제7조 | 고시·공고·법령 등 — 자유 이용 |
KOGL-1 | 공공누리 제1유형 | 출처표시(상업적 이용·변형 허용) |
KOGL-2 | 공공누리 제2유형 | 출처표시 + 비상업적 이용 |
KOGL-3 | 공공누리 제3유형 | 출처표시 + 변경 금지 |
KOGL-4 | 공공누리 제4유형 | 출처표시 + 비상업 + 변경 금지 |
미상 | 등급 미상 | 제목·링크·출처만 보수적으로 인용 |
작고 단일 책임인 모듈로 나뉘어 있어, 각 계층을 독립적으로 테스트·교체할 수 있습니다.
sources ──▶ fetch ──▶ parse ──▶ collect ──▶ report
출처 등록 수집(HTTP/ RSS·JSON 중복제거· Markdown/
+ KOGL등급 오프라인) → Notice 필터·정렬 HTML/JSON
sources.py — 출처 레지스트리(기본 + 사용자 JSON), 각 출처의 KOGL 등급fetch.py — 표준 urllib 수집(http/https만, fail-open) + 로컬 파일 읽기parse.py — RSS/Atom·data.go.kr 파싱, HTML 정리, 날짜 정규화, XML 폭탄 차단collect.py — 오케스트레이션(페처 주입 → 테스트·오프라인이 같은 경로)state.py — 실행 간 상태(신규 감지) — 순수 JSON, 첫 실행은 기준선digest.py — 규칙 기반 기간 요약(기관·분류·키워드) — LLM 없음theme.py — 테마 정의(정준 키워드→동의어·섹션·용어)relevance.py — 관련성 판정(가중치·근거 기록) — LLM 없음cluster.py — 유사 사안 묶음(자카드) — LLM 없음insight.py · chart.py — 해석 계산과 인라인 SVG 그래프deeplink.py — 본문 속 첨부·관련 자료 링크 추출(본문 복제 없음)brief.py · brief_report.py — 테마 브리프 조립·렌더k2web.py · k2web_parse.py · jsonapi.py — 기관 CMS 어댑터(4단 폴백)와 목록·JSON 파서robots.py — robots.txt 준수(호스트별 캐시, fail-open)discover.py — 출처 자동 탐지(RSS 자동발견·K2Web 좌표·검증 스니핑)webui.py — 로컬 웹 UI(조직 선택→수집·검색·탐지, 표준 http.server)webapp.py — 휴대폰 웹 버전의 서버 쪽(기관 목록·기관 하나 수집·경로 캐시·시간 제한·일괄 점검·글 한 건의 그림·첨부). Vercel 함수(api/*.py)와 --web 이 같이 쓴다media.py — 글 화면에서 그림·첨부 주소와 표 개수만 찾기(사이트 껍데기·아이콘·다른 글 썸네일 거르기, 본문 글자 없음)progress.py — 수집 진행 상황 추적(스레드 안전, 남은 시간 어림)categories.py — 메뉴 이름·주소 → 대분류(발견과 요약이 공유하는 사전)govweb.py — 정부 표준홈페이지 게시판 파서(채용·입찰 등 RSS 미제공 목록)cascade.py · govcascade.py — 폴백 공통 뼈대(시도 이력)와 정부 카테고리별 5단 캐스케이드access.py — 접근 진단(전면/경로별 차단 구분, 우리 UA 기준)govpaths.py — 경로 패턴 사이클(홈을 못 읽는 기관용, 데이터 기반)govdiscover.py — 기관 홈에서 수집 경로 자동 발견(후보 수집 → 구조 테스트 선별)slots.py — 학교 갈래 게시판 찾기(공지·학사·장학·입학·채용 — 사이트맵·갈래 화면·하위 사이트)probe.py — 구조 테스트(목록·안내·링크모음·외부 판정)parallel.py — 병렬 실행기와 호스트별 간격(robots Crawl-delay 우선)purposes.py — 목적 동의어 사전(--query 즉석 테마)korean.py — 닫힌 접미(조사·어미) 최장일치 정규화 — pynori 분석의 증류판report.py — Markdown · 자체 완결형 HTML · JSON · 사용자 템플릿 렌더러pip install -e ".[dev]"
pytest -q # 테스트 421개 — 전부 네트워크 없이 동작(페처 주입)
ruff check src tests # 린트
ruff format src tests
CI(GitHub Actions)가 Python 3.10·3.11·3.12 매트릭스로 같은 검사를 돌립니다.
--discover 가
못 찾을 수 있습니다 — 그 경우 게시판 페이지 주소를 직접 지정하세요.govweb 필요).MIT © 2025 — LICENSE 참고.
수집 대상 자료의 저작권은 각 발행 기관에 있으며, 재이용 시 보고서에 표기된
공공누리 등급과 출처표시 조건을 따라야 합니다. open_site_clipper는 원문 본문을
복제하지 않고 제목·링크·발행일 등 메타데이터만 모읍니다.
rights.py — 공공누리 등급 상수·라벨·판정model.py — 도메인 모델(Notice·Report)과 그룹 축(by_agency/by_topic/by_org)cli.py — 명령줄 진입점(인자 검증·한글 콘솔 방어·친절한 오류)