우리 고장 하늘을 엑셀에 적는 파이썬 — 기상·미세먼지 일일 자동 수집기 완전 정복
🌤️ 5~6학년 과학 '날씨와 생활', 실과 데이터 단원. 학생들이 먼저 웹 구조 명세서(specification)(어느 페이지·어느 칸·어느 셀렉터)를 작성하고, 파이썬 스크래퍼(scraper)가 기상청·에어코리아의 실시간 데이터를 매일 아침 수집해 엑셀로 누적합니다.
이번 글의 키워드는 재현성(reproducibility) — 명세서가 있으면 누가 실행해도 같은 결과가 나옵니다. 과학의 재현성 개념이 코드로 몸에 붙는 수업입니다. 공개 데이터만 '받아오는' 도구라 학생 개인정보는 다루지 않으며, 교탁 PC(학내망)에서 실행됩니다.
📖 한 줄 정의
심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).
학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.
1. 3대 핵심 분석 비교표
| 무엇이 바뀌었나요? / 영역 | 초보자를 위한 쉬운 설명 | 이렇게 한번 써보세요! |
|---|---|---|
| 수업 시나리오 | 1차시 명세서 작성 → 2차시 스크래퍼 제작·실행 → 3차시 엑셀 누적·주간 그래프(수학 통계 연계). | 주간 일정표에 3단계를 미리 배치. |
| 웹 구조 명세서 | 페이지 주소·찾을 칸·셀렉터(selector)·수집 주기를 표로 정리한 지도 문서. 셀렉터는 개발자 도구(F12)에서 직접 확인합니다. | 명세서 양식에 '미세먼지' 한 줄을 채워보기. |
| 파이썬 스크래퍼 | requests로 페이지를 받고, BeautifulSoup(HTML 문서 파서)로 칸을 골라냅니다. 셀렉터는 코드 안 상수로 — 명세서와 항상 맞춥니다. | SELECTORS 상수를 명세서에서 옮겨 적기. |
| 엑셀 누적 | openpyxl로 오늘의 기록을 한 줄 추가. 일주일이면 수학 시간 그래프 그리기 재료가 완성됩니다. | 엑셀 파일 열어 새 줄 추가 확인. |
| 원칙·안전 | 공개 데이터 수신만, 외부 전송 0, 학생 개인정보 0. 사이트 구조가 바뀌면? 명세서를 고치고 셀렉터 상수만 교체 — 재현성이 이를 지탱합니다. | '확인 필요' 오류 기록 → 명세서 갱신 루틴. |
2. 핵심 아키텍처 해설 — 명세서가 지도, 스크래퍼는 배
① 웹 구조 명세서 양식
| 항목 | 페이지 주소 | 찾을 칸 | 셀렉터(예시) | 주기 |
|---|---|---|---|---|
| 미세먼지 | airkorea.or.kr | 오늘 미세먼지 수치 | #pm10Value | 하루 1회 |
| 초미세먼지 | 같은 페이지 | 오늘 초미세먼지 수치 | #pm25Value | 하루 1회 |
셀렉터는 예시입니다 — 수업 시점에 개발자 도구로 직접 확인해 명세서에 기록하세요. 명세서가 바뀌지 않는 한, 코드는 언제나 같은 결과를 만듭니다(재현성).
② 페이지 받기: requests
import requests
url = "https://www.airkorea.or.kr/" # 명세서 1행의 페이지 주소(예시)
res = requests.get(url, timeout=10)
res.raise_for_status() # 실패하면 여기서 멈추고 이유를 알려준다
③ 칸 골라내기: 셀렉터는 상수로
from bs4 import BeautifulSoup
SELECTORS = {
"미세먼지": "#pm10Value", # 명세서에서 온 값(예시)
"초미세먼지": "#pm25Value" # 수업 시점에 직접 확인해 교체
}
soup = BeautifulSoup(res.text, "html.parser")
values = {}
for name, sel in SELECTORS.items():
el = soup.select_one(sel)
values[name] = el.get_text(strip=True) if el else "확인 필요"
칸을 찾지 못해도 프로그램이 죽지 않고 '확인 필요'를 기록합니다 — 조용히 실패하는 자동화가 가장 위험합니다.
④ 엑셀 누적: openpyxl
import openpyxl
from datetime import date
wb = openpyxl.load_workbook("우리고장_기록.xlsx")
ws = wb["기록"]
row = ws.max_row + 1
ws.cell(row=row, column=1, value=str(date.today()))
for i, name in enumerate(SELECTORS):
ws.cell(row=row, column=2 + i, value=values[name])
wb.save("우리고장_기록.xlsx")
⑤ 재현성과 운영 원칙
- 명세서 우선: 셀렉터는 항상 명세서에서 코드로 옮긴다 — 코드가 명세서를 바꾸지 않는다.
- 매일 아침 실행: 무인 실행 등록은 작업 스케줄러로 이어집니다.
- 원칙 정합: 공개 데이터 수신만 — 외부 전송 0, 학생 개인정보 0, 교탁 PC 실행.
3. 초보자를 위한 바이브 코딩 실전 사용 예시
- 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 Gemini에 붙여넣습니다.
- 역질문 답변 — 어느 도시, 하루 몇 차, 엑셀 서식 세 질문에 답하면 설계가 고정됩니다.
- 스크립트 실행 — 파이썬 설치 후
python 수집기.py로 실행, 엑셀 파일에서 누적 확인.
제미나이 전용 에러 제로 프롬프트 (파이썬판)
[🚨 에러 방지 기본 안전장치]
1. 라이브러리는 requests, beautifulsoup4, openpyxl 세 가지만 사용한다(설치 부담 최소화).
2. 모든 네트워크 요청에는 timeout을 붙이고, 실패 시 1회 재시도 후 친절한 오류 메시지를 남긴다.
3. 셀렉터는 코드 상단 SELECTORS 상수로 관리하고, 주석에 '명세서 몇 행에서 왔는지'를 표기한다.
4. 칸을 찾지 못하면 프로그램을 중단하지 않고 '확인 필요'를 기록한다(조용한 실패 금지).
5. 엑셀 파일이 이미 열려 있어 저장이 실패하면 '엑셀을 닫고 다시 실행하세요' 안내를 출력한다.
6. 이 스크립트는 공개 데이터를 받아오기만 한다 — 데이터를 외부로 전송하는 기능을 만들지 않는다(학내망 원칙).
7. // TODO, pass 등 미완성 코드 금지 — 끝까지 완성한다.
[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 어느 지역의 기상·미세먼지를 수집할까? (우리 고장 시·군 기준)
Q2. 하루 몇 차 수집이 적당할까? (아침 1회 기본 — 과학 기록 관찰 연계)
Q3. 엑셀 서식은? (날짜 / 미세먼지 / 초미세먼지 3칸 기본)
🎯 에디터 한줄평
'날씨 기록하기'가 '코드에 기록하기'로 — 명세서라는 지도를 먼저 그리는 수업이 재현성을 가르칩니다. 공공데이터는 '받아오는 것'에도 격이 있습니다. 출처를 밝히고, 구조가 바뀌면 명세서를 고치는 자세 — 그것이 시민 데이터 소양의 시작입니다. 일주일 누적이 곧 수학 시간의 그래프 재료가 되는 순환 구조도 아름답습니다.
📚 기술·교육 참고 링크
- 기상청 날씨누리 : 실측으로 정상 응답 확인(2026-09-05)
- 에어코리아 : 대기환경 공개 데이터 — 수업 시점 셀렉터 직접 확인
- requests 공식 문서 : 파이썬 HTTP 요청 표준 라이브러리
- openpyxl 공식 문서 : 엑셀 파일 읽기·쓰기 라이브러리
- 교육과정 연계: 과학(날씨와 생활·환경), 사회(우리 고장), 수학(자료의 수집과 정리)과 함께 활용