개발이 취미인 주니어 기획자

[간단 크롤러 만들기] 튼튼머니 적립시설 크롤러(w/ Selenium & BeautifulSoup) 본문

SW 지식

[간단 크롤러 만들기] 튼튼머니 적립시설 크롤러(w/ Selenium & BeautifulSoup)

큐 2025. 5. 18. 21:52
728x90
반응형


개발자가 안된다고 해서 만들어본 크롤러.. (크롤링이 안된다고 한건 아니고, 검토해 달라고 했는데 검토도 안 해줘서..  안 되는 건 안 되는 거지만 예전부터 크롤링하는 법 궁금하기도 해서 일단 어떻게 할지 찾아봄)

퇴근 후에 커피챗 시간 기다리면서 뚱땅뚱땅 해봤는데 금방 만들었음(따봉지피티야 고마워)

GitHub - qminlee723/web-scraper: when dev team is too busy..

when dev team is too busy.. . Contribute to qminlee723/web-scraper development by creating an account on GitHub.

github.com

~참고로 만든건 3월 중순쯤 만들었음 늦은 포스팅~


1. 개발 목적

  • 국민체육진흥공단의 튼튼머니 적립시설 목록 사이트(https://nfa.kspo.or.kr/spoint/selectSpointFacility.kspo)에서 전국의 적립시설 정보를 자동으로 수집하여 CSV 파일로 저장하는 Python 크롤러
  • 총 적립 시설 수 약 4,000개인데, 한 페이지에 10개 시설만 노출되어 있어 수작업 시간 오래 걸림(약 400 페이지)
  • 자동으로 페이지를 넘겨 데이터 크롤링 하여 표 만들기


2. 기능

  • Selenium을 이용해 페이지를 자동으로 넘기고
  • BeautifulSoup으로 html 파싱(시설명, 지역, 주소, 연락처)
  • 날짜별로 csv 결과 파일 생성


3. csv 파일 구조


지역 | 시설명 | 주소 | 연락처
—— | ——— | —— | ———


4. 코드

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import csv
import time
from datetime import datetime

today = datetime.now().strftime("%Y-%m-%d")
output_file = f"튼튼머니_적립시설_{today}.csv"

columns = ["지역", "시설명", "주소", "연락처"]

with open(output_file, "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.writer(f)
    writer.writerow(columns)

options = webdriver.ChromeOptions()
options.add_argument("--start-maximized")

driver = webdriver.Chrome(options=options)

# 실제 페이지 URL 넣기
driver.get("https://nfa.kspo.or.kr/spoint/selectSpointFacility.kspo")
wait = WebDriverWait(driver, 10)

MAX_PAGE = 402

for page in range(1, MAX_PAGE + 1):
    print(f"📄 페이지 {page} 처리 중...")

    time.sleep(2)  # 페이지 로딩 대기

    # HTML 가져오기
    soup = BeautifulSoup(driver.page_source, "html.parser")
    rows = soup.select("tr")

    page_data = []
    for row in rows:
        mcons = row.select("div.mCont")
        if mcons:
            values = [m.text.strip() for m in mcons]
            if values:
                page_data.append(values)

    with open(output_file, "a", newline="", encoding="utf-8-sig") as f:
        writer = csv.writer(f)
        writer.writerows(page_data)

    print(f"✅ 페이지 {page} 저장 완료 ({len(page_data)}개 항목)")

    # 다음 페이지 클릭 (마지막 페이지는 클릭 X)
    if page < MAX_PAGE:
        try:
            # 페이지네이션 버튼 중 현재 페이지 다음 번호 클릭
            next_page_str = str(page + 1)
            next_button = wait.until(EC.element_to_be_clickable(
                (By.XPATH, f"//a[contains(@onclick, \"pageinfo('{next_page_str}')\")]")))
            next_button.click()
        except Exception as e:
            print(f"❌ 페이지 {page+1} 이동 실패: {e}")
            break

driver.quit()
print(f"🎉 전체 크롤링 완료! 저장된 파일명: {output_file}")


GitHub - qminlee723/web-scraper: when dev team is too busy..

when dev team is too busy.. . Contribute to qminlee723/web-scraper development by creating an account on GitHub.

github.com



뷰티풀숲이니 셀레늄이니 말만 들어봤는데 직접 써봤다. 이쯤 되면 나에게 안된다고 하는 개발팀이 내 자기 계발의 원동력일지도..

개발 말고 나처럼 코딩만 대충 하는 사람들에게 살기 좋은 세상이다.. 간단한 건 큰 노력 없이도 그럴듯하게 다 만들 수 있는 걸

안 좋은 점은 있는 익스텐션/라이브러리 쓰면 되는걸 자꾸 코딩으로 해결 보려고 한다는 거다 ㅋㅋㅋ 몰라 궁금해서 해보고 싶은데 어떡해? 하고 싶으면 하는 거지 흥

내 주언어는 쟈스인데.. 이런 걸 자꾸 파이썬으로 맹글다 보니까 이제 파이썬이 좀 더 익숙한 거 같기도 하고~


qminlee723 - Overview

An aspiring learner with a strong interest in front-end development. Seeking opportunities to build my portfolio and gain real-world experience. since 2022 🌱 - qminlee723

github.com

또 뭐를 만들고 있는지 궁금하면 와보시조!

728x90
반응형