DB_JOB/작업파일/완료_1-2주차/1주차(5.19~5.25)/교육부(완료)/크롤링.py
hehihoho3 df16c98366 백업: DB수집 전체 스냅샷 (공공기관2 정리 전)
공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:15:40 +09:00

139 lines
6.5 KiB
Python

import openpyxl
import requests
from bs4 import BeautifulSoup
import re
import time
def crawl_moe_license_separate_save(origin_path, save_path, sheet_name=None):
"""
교육부 엑셀 리스트 맞춤형 크롤러 (원본 읽기 -> 크롤링 -> 별도 파일로 저장)
"""
try:
# 1. 원본 엑셀 파일 로드
wb = openpyxl.load_workbook(origin_path)
ws = wb[sheet_name] if sheet_name else wb.active
print(f"📂 원본 파일을 성공적으로 불러왔습니다: {origin_path}")
except Exception as e:
print(f"❌ 원본 엑셀 파일을 열 수 없습니다. 경로를 확인해주세요. 에러: {e}")
return
# 웹 서버 차단 방지용 User-Agent 설정
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'
}
print("🚀 교육부 공공누리 라이선스 크롤링을 시작합니다. (대상: 3행 ~ 마지막 행)")
# 3행부터 데이터가 있는 마지막 행까지 순회
for row in range(3, ws.max_row + 1):
url_cell = ws.cell(row=row, column=11).value # K열 (11번째 열)
if not url_cell:
continue
url = str(url_cell).strip()
# [예외 처리] URL에 특정 도메인(www.moe.go.kr)이 포함되어 있지 않은 경우 처리
if 'www.moe.go.kr' not in url:
ws.cell(row=row, column=12, value="사이트") # L열: 사이트 명시
ws.cell(row=row, column=13, value="") # M열: 빈칸
ws.cell(row=row, column=15, value="") # O열: 빈칸
ws.cell(row=row, column=16, value="") # P열: 빈칸
ws.cell(row=row, column=17, value="") # Q열: 빈칸
print(f"[{row}행] 외부 도메인 필터링 -> '사이트' 분류 처리")
continue
try:
# 웹페이지 요청 (타임아웃 10초 설정)
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
# 인코딩 설정
response.encoding = response.apparent_encoding
soup = BeautifulSoup(response.text, 'html.parser')
# --- 1단계. L열 / M열: 게시판 형태 및 수량 판별 ---
board_top_div = soup.find('div', {'data-board': 'top'})
is_board = False
total_count = None
if board_top_div:
strong_tag = board_top_div.find('strong')
if strong_tag:
span_tag = strong_tag.find('span')
if span_tag:
# 숫자 데이터만 추출
count_text = re.sub(r'[^0-9]', '', span_tag.text)
if count_text:
total_count = int(count_text)
is_board = True
# 형태 판별 결과 저장 (대시 대신 무조건 빈칸 규칙 적용)
if is_board:
ws.cell(row=row, column=12, value="게시판") # L열
ws.cell(row=row, column=13, value=total_count) # M열
else:
ws.cell(row=row, column=12, value="페이지") # L열
ws.cell(row=row, column=13, value="") # M열 (빈칸)
# --- 2단계. O, P, Q열: <div id="content"> 본문 영역 라이선스 탐색 ---
content_area = soup.find('div', id='content')
license_type = "미부착"
mark_location = "" # 미부착 시 기본 빈칸
has_license = "N"
if content_area:
content_str = str(content_area)
# 공공누리 통합 식별 패턴
type_match = re.search(r'kogl_img([1-4])|licenseType=([1-4])|type([1-4])_bg|kogl_type([1-4])', content_str, re.IGNORECASE)
if type_match:
matched_num = next(g for g in type_match.groups() if g is not None)
license_type = f"{matched_num}유형"
mark_location = "게시판" if is_board else "페이지"
has_license = "Y"
# 규정된 열 자리에 매칭 결과 입력
ws.cell(row=row, column=15, value=license_type) # O열
ws.cell(row=row, column=16, value=mark_location) # P열
ws.cell(row=row, column=17, value=has_license) # Q열
print(f"[{row}행] 형태: {ws.cell(row=row, column=12).value} | 건수: {ws.cell(row=row, column=13).value} | 결과: {license_type}")
except requests.exceptions.RequestException as e:
# 접속 에러나 사이트 다운 시 대시 대신 빈칸 처리 규칙 엄수
ws.cell(row=row, column=12, value="에러")
ws.cell(row=row, column=13, value="")
ws.cell(row=row, column=15, value="접속불가")
ws.cell(row=row, column=16, value="")
ws.cell(row=row, column=17, value="N")
print(f"[{row}행] 웹 접속 실패 (Error: {e})")
# 서버 부하 방지를 위한 미세 지연 설정 (0.5초)
time.sleep(0.5)
# 새로운 파일 경로로 안전하게 저장
try:
wb.save(save_path)
wb.close()
print(f"🎯 작업 완료! 새로운 파일이 성공적으로 저장되었습니다: {save_path}")
except PermissionError:
print("❌ 에러: 저장하려는 새 파일이 이미 열려 있어 저장할 수 없습니다. 파일을 닫고 다시 실행해주세요.")
# ================================================================= #
# [실행부] r"" 안에 불러올 파일과 저장할 파일 경로를 각각 적어주세요.
# ================================================================= #
if __name__ == "__main__":
# 1. 읽어올 원본 파일 경로
ORIGIN_EXCEL_PATH = r"C:\Users\hehih\ownCloud\알바\교육부\교육부_사이트맵_r2.xlsx"
# 2. 결과물이 저장될 새로운 파일 경로
SAVE_EXCEL_PATH = r"C:\Users\hehih\ownCloud\알바\교육부\교육부_사이트맵_r3.xlsx"
TARGET_SHEET_NAME = "조사양식" # 작업할 시트 이름
# 실행
crawl_moe_license_separate_save(ORIGIN_EXCEL_PATH, SAVE_EXCEL_PATH, TARGET_SHEET_NAME)