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

98 lines
4.5 KiB
Python

import os
import time
import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
from openpyxl import load_workbook
def fill_board_counts_only(file_path, output_path):
# 1. 원본 서식을 그대로 유지하기 위해 openpyxl로 로드
wb = load_workbook(file_path)
ws = wb.active
# openpyxl 열 번호 지정 (1부터 시작)
K_col = 11 # K열 (URL)
L_col = 12 # L열 (게시판구분)
M_col = 13 # M열 (수량/건수)
# 강력한 웹 크롤링 세션 구성
session = requests.Session()
retry_strategy = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
session.headers.update({
"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",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7",
})
total_rows = ws.max_row
print(f"{total_rows}행이 확인되었습니다. 87행부터 L/M열 수집을 시작합니다...\n")
# 87행부터 마지막 행까지 순차적으로 탐색
for current_row in range(87, total_rows + 1):
target_url = str(ws.cell(row=current_row, column=K_col).value).strip()
# URL 주소가 비어있거나 올바르지 않으면 패스
if not target_url.startswith("http") or target_url == "None":
print(f"[{current_row} / {total_rows}행] -> URL이 없거나 올바르지 않습니다. (건너뜀)")
continue
print(f"[{current_row} / {total_rows}행] 처리 중... -> URL: {target_url}")
# 1. K열 URL이 /list.do로 끝나는지 검사
# 쿼리 스트링(?...)이 붙어 있을 수 있으므로 분리 후 매칭
url_path = target_url.split('?')[0]
if url_path.endswith("/list.do"):
# L열에 '게시판' 작성
ws.cell(row=current_row, column=L_col).value = "게시판"
# 방화벽 우회를 위한 안전 딜레이
time.sleep(0.5)
try:
session.headers.update({"Referer": target_url})
response = session.get(target_url, timeout=15)
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
# 2. <div class="total"> 전체 <span>숫자</span> 건 </div> 탐색
total_div = soup.find("div", class_="total")
if total_div and total_div.find("span"):
count_text = total_div.find("span").get_text(strip=True)
# 숫자가 정상적이라면 M열에 정수형 숫자로 입력
if count_text.isdigit():
ws.cell(row=current_row, column=M_col).value = int(count_text)
print(f" -> [성공] '게시판' 마킹 및 건수 기입 완료: {count_text}")
else:
ws.cell(row=current_row, column=M_col).value = count_text
print(f" -> [주의] 텍스트 건수 기입: {count_text}")
else:
print(" -> [알림] 게시판 형태이나 total 건수 태그를 찾지 못했습니다.")
else:
print(f" -> [실패] HTTP 응답 에러 코드: {response.status_code}")
except Exception as e:
print(f" -> [오류] 웹페이지 접속 및 파싱 실패: {e}")
else:
# /list.do로 끝나지 않는 일반 페이지 처리
ws.cell(row=current_row, column=L_col).value = "페이지"
print(" -> 일반 '페이지'입니다. (건수 수집 패스)")
# 스타일 유지 상태로 안전하게 저장
wb.save(output_path)
print(f"\n✨ 수집이 전부 완료되었습니다! 파일 저장 완료:\n{output_path}")
# --- 실행 영역 ---
input_excel = r"C:\Users\hehih\ownCloud\알바\2주차\외교부\외교부_업데이트_활성화_r4.xlsx"
output_excel = r"C:\Users\hehih\ownCloud\알바\2주차\외교부\외교부_업데이트_활성화_r5.xlsx"
fill_board_counts_only(input_excel, output_excel)