DB_JOB/작업파일/완료_1-2주차/2주차/보건복지부/test.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

166 lines
7.7 KiB
Python

import os
import re
import time
import requests
from bs4 import BeautifulSoup
import openpyxl
from openpyxl.utils import get_column_letter
def analyze_mohw_site(excel_path):
# 1. 엑셀 파일 로드
if not os.path.exists(excel_path):
print(f"파일을 찾을 수 없습니다: {excel_path}")
return
wb = openpyxl.load_workbook(excel_path)
ws = wb.active # 현재 활성화된 시트 선택
# 기본 도메인 정의
base_url = "https://www.mohw.go.kr"
# 웹 요청 시 사용할 User-Agent 설정 (차단 방지)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
print("크롤링 및 분석을 시작합니다...")
# 2. 3행부터 마지막 행까지 루프 수행
max_row = ws.max_row
for row in range(3, max_row + 1):
url = ws.cell(row=row, column=11).value # K열 (11번째)
# URL이 비어있으면 건너뜀
if not url:
continue
url = url.strip()
print(f"[{row}/{max_row} 행 분석 중] URL: {url}")
# 예외 처리: K열에 www.mohw.go.kr이 포함되어 있지 않은 경우
if "www.mohw.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열
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')
time.sleep(1.0) # 디레이 시간 부여 (1초)
# 게시판 형태 및 수량 판별 로직 (L열, M열)
board_type = "페이지"
total_count = ""
# 패턴 A 탐색: <strong id="totalCount">
total_count_tag_a = soup.find(id="totalCount")
# 패턴 B 탐색: <span class="total"><b>
total_count_tag_b = soup.select_one("span.total b")
if total_count_tag_a:
count_text = total_count_tag_a.get_text(strip=True)
# 숫자만 추출
numbers = re.findall(r'\d+', count_text)
if numbers:
total_count = int(numbers[0])
board_type = "게시판"
elif total_count_tag_b:
count_text = total_count_tag_b.get_text(strip=True)
numbers = re.findall(r'\d+', count_text)
if numbers:
total_count = int(numbers[0])
board_type = "게시판"
# 판별 결과 기록 (L열, M열)
ws.cell(row=row, column=12, value=board_type)
ws.cell(row=row, column=13, value=total_count) # 페이지일 경우 total_count가 ""이므로 빈칸 처리됨
# 초기 결과 변수 설정
license_type = "미부착"
mark_location = ""
has_mark = ""
# 공공누리 마크 식별을 위한 변수 (현재 정보가 없으므로 미부착 처리용 플래그)
found_license = False
if board_type == "게시판":
# --- [게시판 로직] ---
# 1차 탐색 영역 (목록화면 전체 body 혹은 특정 영역 내에서 라이선스 탐색 가능)
# 여기서는 목록 화면 전체에서 우선 매칭되는지 체크 가능 (필요시 영역 축소 가능)
# 상세 페이지 URL 추출 (최대 5개 크롤링)
detail_links = []
list_table = soup.find("table", class_="tstyle_list")
if list_table:
a_tags = list_table.select("td.txt_left a")
for a in a_tags[:5]: # 상위 5개만 추출
href = a.get("href", "")
if href:
# 상대 경로일 경우 절대 경로로 결합
if href.startswith("/"):
detail_links.append(base_url + href)
elif href.startswith("http"):
detail_links.append(href)
else:
detail_links.append(base_url + "/" + href)
# 2차 탐색 영역 (상세 글 5개 순회)
for detail_url in detail_links:
try:
detail_res = requests.get(detail_url, headers=headers, timeout=10)
detail_res.raise_for_status()
detail_res.encoding = detail_res.apparent_encoding
detail_soup = BeautifulSoup(detail_res.text, 'html.parser')
time.sleep(0.8) # 상세 페이지 요청 간 디레이
# 상세페이지 본문 영역 선택: <article class="board_view">
article_body = detail_soup.find("article", class_="board_view")
if article_body:
# 💡 [추후 수정 공간] 공공누리 마크 식별 패턴이 정의되면 이곳에 코드를 삽입합니다.
# 예: if "kogl" in str(article_body): ...
pass
except Exception as e:
print(f"상세 페이지 접근 오류 ({detail_url}): {e}")
continue
else:
# --- [페이지 로직] ---
# 본문 영역 선택: <div id="contents_body">
contents_body = soup.find(id="contents_body")
if contents_body:
# 💡 [추후 수정 공간] 공공누리 마크 식별 패턴이 정의되면 이곳에 코드를 삽입합니다.
pass
# 최종 결과 기록 (O, P, Q열)
ws.cell(row=row, column=15, value=license_type)
ws.cell(row=row, column=16, value=mark_location)
ws.cell(row=row, column=17, value=has_mark)
except Exception as e:
print(f"{row}행 처리 중 오류 발생: {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="")
# 3. 엑셀 파일 저장
output_path = excel_path.replace(".xlsx", "_결과.xlsx")
wb.save(output_path)
print(f"모든 분석이 완료되었습니다. 결과가 저장되었습니다: {output_path}")
# 코드 실행부 (파일명이 'target_list.xlsx'인 경우 예시)
if __name__ == "__main__":
# 처리하고자 하는 엑셀 파일 경로를 입력하세요.
excel_file_path = r"D:\01.프로젝트\DB수집\2주차\보건복지부\보건복지부_활성화.xlsx"
analyze_mohw_site(excel_file_path)