Files
Aislo/resources/knowledge/original/_pipeline/check_law.py
T
eomsangdonandClaude Fable 5 81cd7e23c3 feat(knowledge): 도메인 지식저장소 메인 통합 + resources 그룹 체계 재편
knowledge (구 Aislo-law 독립 저장소 → resources/knowledge 이관, 저장소 폐지):
- 법령·행정규칙·표준시방서·교본 원문 + 기술문서 55건 + 실무 분석·종합비교
- 루트 지침 체계: README(지도)·00_운영지침·01_수집지침·02_분석지침·
  03_미결_및_확인사항(교본 충돌 리스트 포함)·04_참조_법령기준_목록
- 기술문서 55건 원문 전수 검증 완료 (사방 설계홍수량 법정 기준 등 반영)
- 정리: CAD·오피스 잔재 142건, 중복 zip 7건(413MB), 빈 폴더 30개 제거

resources 그룹 재편 (이름순 그룹핑):
- app_branding(구 prog_icon.jpg)·app_policies(구 legal)·
  data_global_contours(구 grobal_contours)·data_rainfall_idf_cache(구 wamis_contours)·
  template_2dDrawing(구 dwg_analysis/templete — 오타 교정, 상수·경로 동기화)
- dwg_analysis(분석 완료 1.8GB)·templates(빈 폴더)·templete_calc_cost.xlsx 삭제
- 참조 코드 5파일 경로 수정 + 프론트 재빌드 (구 경로 잔존 0)
- .gitignore: resources 추적 전환, national_contours.gpkg(22GB) 영구 제외
- .env: knowledge 수집용 API 정보 주석 통합 (KCSC·법령센터·조달청 제비율)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 19:14:32 +09:00

112 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
"""국가법령정보센터 Open API로 목록 항목의 보유 여부·시행일·개정일 조회."""
import json, re, time, urllib.parse, urllib.request
from pathlib import Path
import os as _os
from pathlib import Path as _P
# 이 스크립트는 original/_pipeline/ 에 위치. 코퍼스 루트 = 상위 폴더.
ROOT_DIR = _P(__file__).resolve().parent.parent # ...\original
DATA_DIR = _P(__file__).resolve().parent / "data" # 생성 데이터(JSON)
# API 키: 커밋 금지 파일(law/.secrets.local.md) 또는 환경변수에서 읽는다.
def _load_key(name):
v = _os.environ.get(name)
if v: return v.strip()
sec = ROOT_DIR.parent / ".secrets.local.md"
if sec.exists():
import re as _re
for pat in (r"KCSC[\s\S]*?`([A-Za-z0-9]{20,})`", r"인증키[:\s]*`?([A-Za-z0-9]{30,})`?"):
m = _re.search(pat, sec.read_text(encoding="utf-8"))
if m: return m.group(1)
return ""
import xml.etree.ElementTree as ET
OUT = Path(str(DATA_DIR))
def api(target, query, display=5):
url = ("https://www.law.go.kr/DRF/lawSearch.do?OC=umsangdon&type=XML"
f"&target={target}&display={display}&query=" + urllib.parse.quote(query))
for _ in range(3):
try:
with urllib.request.urlopen(url, timeout=25) as r:
return ET.fromstring(r.read())
except Exception as e:
time.sleep(1.2)
return None
def txt(node, *names):
for n in names:
el = node.find(n)
if el is not None and el.text:
return el.text.strip()
return ""
def ymd(s):
s = re.sub(r"\D", "", s or "")
return f"{s[:4]}.{s[4:6]}.{s[6:8]}" if len(s) == 8 else ""
LAWS = [
"산림자원의 조성 및 관리에 관한 법률", "산림자원의 조성 및 관리에 관한 법률 시행령",
"산림자원의 조성 및 관리에 관한 법률 시행규칙", "산림기술 진흥 및 관리에 관한 법률",
"산림기술 진흥 및 관리에 관한 법률 시행령", "산림보호법", "산지관리법",
"자연환경보전법", "자연재해대책법", "환경영향평가법", "국가균형발전특별법",
"보조금 관리에 관한 법률", "국가를 당사자로 하는 계약에 관한 법률",
"국가를 당사자로 하는 계약에 관한 법률 시행령",
"지방자치단체를 당사자로 하는 계약에 관한 법률",
"지방자치단체를 당사자로 하는 계약에 관한 법률 시행령",
"도로법", "농어촌도로 정비법", "국토의 계획 및 이용에 관한 법률",
"도로명주소법", "도로명주소법 시행령", "공간정보의 구축 및 관리 등에 관한 법률",
"산업안전보건법", "산업재해보상보험법",
"고용보험 및 산업재해보상보험의 보험료징수 등에 관한 법률",
"고용보험 및 산업재해보상보험의 보험료징수 등에 관한 법률 시행령",
"고용보험법 시행령", "국민건강보험법", "국민연금법", "노인장기요양보험법",
"노인장기요양보험법 시행령", "부가가치세법", "근로기준법", "산업표준화법",
"전자서명법", "공동주택관리법",
]
RULES = [
"임도설치 및 관리 등에 관한 규정",
"산림관리기반시설의 설계 및 시설기준",
"산림관리기반시설의 범위 및 기준",
"산림관리기반시설의 타당성평가",
"임도 품셈",
"자연휴양림업무 처리지침",
"중기운용관리",
"훈령·예규 등의 발령 및 관리에 관한 규정",
"국가지점번호",
"재난구호 및 재난복구 비용 부담기준 등에 관한 규정",
"사업종류별 산재보험료율",
"건설업 산업안전보건관리비 계상 및 사용기준",
"사회보험의 보험료 적용기준",
"엔지니어링사업대가의 기준",
"예산안 편성",
"토목공사원가계산 제비율",
"입찰유의서",
"수치지도 작성 작업규칙",
"비산분진 발생원 시설관리기준",
"건설공사 감독자 업무 지침",
"콘크리트 표준시방서", "도로공사 표준시방서", "임도시설공사 표준시방서",
]
res = {}
for grp, target, items in (("법령", "law", LAWS), ("행정규칙", "admrul", RULES)):
for q in items:
root = api(target, q)
rows = []
if root is not None:
for node in root.findall("law") + root.findall("admrul"):
rows.append({
"명": txt(node, "법령명한글", "행정규칙명"),
"약칭": txt(node, "법령약칭명"),
"종류": txt(node, "법령구분명", "행정규칙종류"),
"부처": txt(node, "소관부처명", "소관부처명"),
"공포": ymd(txt(node, "공포일자", "발령일자")),
"시행": ymd(txt(node, "시행일자")),
"제개정": txt(node, "제개정구분명", "제개정구분코드"),
"번호": txt(node, "공포번호", "발령번호"),
})
res[q] = {"grp": grp, "target": target, "rows": rows}
print(f"[{grp}] {q} -> {len(rows)}건" + (f" | {rows[0]['명']} 시행 {rows[0]['시행']}" if rows else ""))
time.sleep(0.35)
json.dump(res, open(OUT / "lawapi.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1)