티스토리 뷰

반응형

 

 

웹 스크래퍼 기반 가격 알림 프로젝트 개요

 

 

파이썬 실전 프로젝트: 웹 스크래퍼 기반 가격 비교 알리미 만들기 🐍💸

 

📘 서론

 

온라인 쇼핑이 생활의 일부가 된 오늘, 같은 상품이라도 가격이 수시로 변한다. 원하는 가격에 떨어졌을 때 즉시 알림을 받으면 합리적 소비에 큰 도움이 된다. 본 프로젝트는 requests와 BeautifulSoup로 가격을 스크래핑하고, 조건 충족 시 이메일로 알려주는 실전 자동화 도구를 만든다.

 

 

 

 

 

환경 준비 및 라이브러리 설치

모니터링 대상과 설정값 분석

 

 

 

 

🧭 본론

 

🔧 환경 준비와 필수 라이브러리 설치  

먼저 터미널에서 다음 명령어로 라이브러리를 설치한다.  

pip install requests beautifulsoup4  

이 두 패키지가 웹 요청과 HTML 파싱을 담당한다. 추가로 이메일 전송은 파이썬 내장 smtplib를 사용한다.

 

🔎 1) 모니터링 대상과 설정 부분 분석  

스크립트 상단에서 모니터링할 URL과 목표 가격, HTML 선택자 등을 정의한다. 실제 동작하려면 브라우저 개발자 도구(F12)로 가격이 위치한 태그의 클래스나 id를 정확히 확인해야 한다. 예를 들어 PRICE_SELECTOR는 다음처럼 설정한다.

 

PRODUCT_URL = "https://www.example-shopping-mall.com/product/12345"  

TARGET_PRICE = 95000  

PRICE_SELECTOR = "span.price_display"

 

위 변수들은 스크립트 동작의 핵심이므로 실사용 시 반드시 교체한다. 목표 가격은 정수형으로 설정하고, 선택자는 CSS 선택자 형식으로 입력한다.

 

 

 

 

가격 추출 함수(get_product_price) 핵심 로직과 실무 팁

 

 

 

 

🕵️‍♂️ 2) 가격 추출 함수(get_product_price) 해설  

가격을 가져오는 핵심 함수는 requests로 HTML을 요청하고, BeautifulSoup으로 파싱하여 지정한 선택자를 찾는다. 다음은 핵심 로직의 요약이다.

 

headers = { 'User-Agent': 'Mozilla/5.0 ...' }  

response = requests.get(url, headers=headers, timeout=10)  

soup = BeautifulSoup(response.text, 'html.parser')  

price_element = soup.select_one(selector)

 

가격 텍스트에서 숫자를 뽑아 정수로 변환한다. 정규표현식 re.sub(r'[^\d]', '', price_text)를 사용하면 원화 기호와 쉼표를 제거할 수 있다. 요청에는 timeout과 User-Agent를 설정해 서버 차단 가능성을 낮춘다.

 

⚠️ 실무 팁: 스크래핑 시 사이트의 robots.txt와 이용약관을 확인한다. 반복 요청은 사이트에 부담을 줄 수 있으니 sleep 간격을 두거나 주기적 실행은 합리적 빈도로 설정한다.

 

 

 

 

이메일 발송 함수 구현 및 보안

메인 로직과 주기적 실행(크론/작업 스케줄러)

 

 

 

 

✉️ 3) 이메일 발송 함수(send_email_notification) 설명  

가격이 목표 이하일 때 이메일을 보내는 부분이다. smtplib을 사용해 SMTP 서버에 접속하고 TLS로 보안 연결을 설정한다. Gmail을 사용할 경우 앱 비밀번호를 발급받아 PASSWORD 변수에 넣어야 한다. 이메일 본문은 MIMEText로 HTML 형식을 지정하면 가독성이 좋아진다.

 

server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)  

server.starttls()  

server.login(SENDER_EMAIL, PASSWORD)  

server.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, msg.as_string())

 

보안 포인트: 실제 코드에 비밀번호를 하드코딩하기보다 환경변수나 암호화된 비밀관리 서비스 사용을 권장한다.

 

⏱️ 4) 메인 로직과 자동 실행  

main 함수는 가격을 가져와 목표 가격과 비교한다. 조건이 맞으면 이메일 함수를 호출한다. 스크립트를 주기적으로 실행하려면 운영체제의 스케줄러를 사용한다. Linux/macOS는 cron, Windows는 작업 스케줄러(Task Scheduler)를 활용하면 된다.

 

예: cron에 매 시간 실행 설정하면 24시간 모니터링이 가능하다. 다만 너무 잦은 실행은 차단 위험이 있으므로 10분~1시간 단위를 권장한다.

 

 

 

 

 

기술적 고려사항 및 개선 아이디어
동적 로딩 페이지 처리
실패 재시도 로직 및 백오프 전략
다수 상품 동시 추적을 위한 데이터 관리
알림 방식 확장(카카오톡·텔레그램·슬랙)

코드 설명 흐름

모니터링 대상 및 목표 가격 설정
이메일 발송 정보 설정
가격 추출 핵심 로직(BeautifulSoup 활용)
이메일 발송 핵심 로직(smtplib 활용)

자주 묻는 질문(FAQ)

가격 태그 미발견 시 확인 방법
Gmail 이메일 전송 실패 시 해결 방법
자바스크립트 렌더링 대응 방법

결론

검색 키워드

전체 코드 (price_tracker.py)

1. 설정: 모니터링 대상 및 목표 가격
2. 설정: 이메일 알림 정보
3. 함수: 웹 페이지에서 현재 가격 가져오기
4. 함수: 이메일 알림 발송
5. 메인 실행 로직

 

 

 

 

🔬 기술적 고려사항 및 개선 아이디어  

- 동적 로딩 페이지 처리: 자바스크립트로 가격을 렌더링하는 사이트는 requests로는 값이 보이지 않는다. 이 경우 Selenium 같은 브라우저 자동화 도구를 고려한다.  

- 실패 재시도 로직: 네트워크 오류 발생 시 재시도와 백오프(backoff)를 구현하면 안정성이 높아진다.  

- 여러 상품 동시 추적: 상품 정보를 파일이나 DB로 관리하고 반복문으로 처리하면 확장성이 생긴다.  

- 알림 방식 추가: 이메일 외에 카카오톡, 텔레그램 봇, 슬랙 등으로 알림을 확장하면 편리하다.

 

🧩 코드 설명 흐름 (부분별로)  

아래는 스크립트의 주요 부분을 발췌해 설명한 것이다. 코드 전체는 마지막에 한꺼번에 제공한다.

 

1) 설정(모니터링 대상)

PRODUCT_URL = "https://www.example-shopping-mall.com/product/12345"  

TARGET_PRICE = 95000  

PRICE_SELECTOR = "span.price_display"

 

2) 이메일 정보 설정

SENDER_EMAIL = "your_sender_email@gmail.com"  

RECEIVER_EMAIL = "your_receiver_email@example.com"  

PASSWORD = "YOUR_GMAIL_APP_PASSWORD"  

SMTP_SERVER = "smtp.gmail.com"  

SMTP_PORT = 587

 

3) 가격 추출 핵심 부분

headers = {'User-Agent': 'Mozilla/5.0 ...'}  

response = requests.get(url, headers=headers, timeout=10)  

soup = BeautifulSoup(response.text, 'html.parser')  

price_element = soup.select_one(selector)  

numeric_price = re.sub(r'[^\d]', '', price_text)

 

4) 이메일 발송 핵심 부분

msg = MIMEText(body, 'html')  

server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)  

server.starttls()  

server.login(SENDER_EMAIL, PASSWORD)  

server.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, msg.as_string())

 

🧾 Q&A

 

Q. 특정 쇼핑몰에서 가격 태그를 못 찾습니다. 어떻게 확인하나요?  

A. 브라우저에서 상품 페이지를 연 뒤 F12를 눌러 개발자 도구를 연다. 가격을 마우스 오른쪽 클릭 후 '요소 검사'로 정확한 태그와 클래스/아이디를 확인한다. CSS 선택자는 그 정보를 바탕으로 작성한다.

 

Q. Gmail로 이메일 전송이 실패합니다. 해결 방법은?  

A. Gmail은 일반 비밀번호 대신 앱 비밀번호를 요구한다. 구글 계정 보안에서 2단계 인증을 켠 뒤 앱 비밀번호를 생성해 사용한다. 또한 SMTP 포트와 TLS 사용 여부를 확인한다.

 

Q. 자바스크립트로 가격이 렌더링되면 어떻게 하나요?  

A. requests로는 HTML에 가격 정보가 없을 수 있다. 이 경우 Selenium이나 Playwright 같은 브라우저 자동화 툴로 렌더링된 페이지에서 값을 읽어야 한다.

 

🔚 결론

 

이번 프로젝트는 웹 스크래핑과 이메일 자동화를 통합한 실용적인 예제다. 작은 코드 몇 줄로 시간과 노력을 절약할 수 있다. 먼저 한 상품으로 테스트한 뒤, 확장성과 예외 처리를 보완하면서 실무용으로 발전시키자. 오늘 바로 원하는 상품을 등록해 목표가에 도달했을 때의 쾌감을 경험해 보시길 바란다.

 

공감하셨다면 하트 꾹 눌러주세요

 

검색 키워드 줄  

#파이썬프로젝트 #웹스크래핑 #가격알리미 #requests #BeautifulSoup #smtplib #자동화툴 #가격비교 #Python #이메일알림 #웹크롤러 #쇼핑알림 #앱비밀번호 #Selenium #크론스케줄러

 

풀 코드 (전체파일: price_tracker.py)

 

# -*- coding: utf-8 -*-

import requests

from bs4 import BeautifulSoup

import smtplib

from email.mime.text import MIMEText

import time

import re

import os

 

 

# ========================================================================

# 1. 설정: 모니터링 대상 및 목표 가격 설정

# ========================================================================

 

 

# 주의: 실제 웹사이트의 HTML 구조가 변경될 수 있으므로, 반드시 F12 개발자 도구로 클래스나 ID를 확인 후 수정해야 합니다.

# 예시 URL (실제 동작을 위해서는 유효한 URL로 대체해야 합니다)

PRODUCT_URL = "https://www.example-shopping-mall.com/product/12345"

# 목표 가격 (이 가격 이하일 경우 알림 발송)

TARGET_PRICE = 95000

# 실제 가격을 가져올 때 사용할 HTML 요소 선택자 (가장 흔한 패턴을 사용합니다)

# 예시: <span class="price_display">99,000</span>

PRICE_SELECTOR = "span.price_display"

 

 

 

 

# ========================================================================

# 2. 설정: 이메일 알림 정보 설정

# ========================================================================

 

 

# 이메일 발송 정보 (Gmail 기준)

SENDER_EMAIL = "your_sender_email@gmail.com"  # 발신자 이메일 주소

RECEIVER_EMAIL = "your_receiver_email@example.com"  # 수신자 이메일 주소

# Gmail 앱 비밀번호 (일반 비밀번호 대신 사용해야 합니다)

PASSWORD = "YOUR_GMAIL_APP_PASSWORD"

SMTP_SERVER = "smtp.gmail.com"

SMTP_PORT = 587

 

 

# ========================================================================

# 3. 함수: 웹 페이지에서 현재 가격 가져오기

# ========================================================================

def get_product_price(url, selector):

    """

    주어진 URL에서 상품 가격을 스크래핑하여 정수형으로 반환합니다.

    """

    try:

        # 웹사이트의 접근을 봇으로 인식하지 않도록 User-Agent 설정

        headers = {

            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'

        }

       

        # 페이지 내용 요청

        response = requests.get(url, headers=headers, timeout=10)

        response.raise_for_status() # HTTP 오류 발생 시 예외 발생

       

        # BeautifulSoup을 이용해 HTML 파싱

        soup = BeautifulSoup(response.text, 'html.parser')

       

        # 지정된 CSS 선택자로 가격 요소 찾기

        price_element = soup.select_one(selector)

       

        if price_element:

            # 텍스트에서 숫자만 추출하고 쉼표 제거 (예: '99,000원' -> '99000')

            price_text = price_element.get_text()

            numeric_price = re.sub(r'[^\d]', '', price_text)

           

            if numeric_price:

                current_price = int(numeric_price)

                print(f"현재 가격 추출 성공: {current_price}원")

                return current_price

            else:

                print("오류: 가격 텍스트에서 숫자를 추출하지 못했습니다.")

                return None

        else:

            print(f"오류: HTML에서 지정된 선택자 '{selector}'를 찾을 수 없습니다.")

            return None

 

 

    except requests.exceptions.RequestException as e:

        print(f"웹 요청 중 오류 발생: {e}")

        return None

    except Exception as e:

        print(f"가격 스크래핑 중 알 수 없는 오류 발생: {e}")

        return None

 

 

# ========================================================================

# 4. 함수: 이메일 알림 발송

# ========================================================================

def send_email_notification(current_price, target_price, product_url):

    """

    이메일을 통해 가격 알림을 발송합니다.

    """

    subject = f"[가격 알림!] 목표가 달성: {target_price:,}원 이하!"

    body = f"""

    안녕하세요. 파이썬 가격 알리미입니다.

 

 

    상품 가격이 목표가({target_price:,}원) 이하로 떨어졌습니다!

 

 

    - 현재 가격: {current_price:,}원

    - 목표 가격: {target_price:,}원

    - 상품 링크: {product_url}

 

 

    지금 바로 확인하세요!

    """

 

 

    # MIMEText 객체 생성 (HTML 형식으로 설정하여 가독성을 높입니다)

    msg = MIMEText(body, 'html')

    msg['Subject'] = subject

    msg['From'] = SENDER_EMAIL

    msg['To'] = RECEIVER_EMAIL

   

    try:

        # TLS 보안 연결 설정

        server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)

        server.starttls()  

       

        # 로그인

        server.login(SENDER_EMAIL, PASSWORD)

       

        # 이메일 전송

        server.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, msg.as_string())

       

        print("✅ 이메일 알림 발송 성공!")

   

    except Exception as e:

        print(f"❌ 이메일 발송 중 오류 발생: {e}")

    finally:

        if 'server' in locals():

            server.quit()

 

 

# ========================================================================

# 5. 메인 실행 로직

# ========================================================================

def main():

    """

    스크래핑을 실행하고 가격을 비교하여 알림을 보낼지 결정합니다.

    """

    print("--- 파이썬 가격 알리미 시작 ---")

   

    current_price = get_product_price(PRODUCT_URL, PRICE_SELECTOR)

 

 

    if current_price is None:

        print("❌ 가격 정보를 가져오는 데 실패했습니다. 다음 주기에 다시 시도합니다.")

        return

 

 

    print(f"현재 가격: {current_price:,}원 | 목표 가격: {TARGET_PRICE:,}원")

 

 

    if current_price <= TARGET_PRICE:

        print("🎉 목표 가격 달성! 이메일 알림을 발송합니다.")

        send_email_notification(current_price, TARGET_PRICE, PRODUCT_URL)

    else:

        print("⏳ 아직 목표 가격에 도달하지 않았습니다. 다음 주기를 기다립니다.")

       

    print("--- 파이썬 가격 알리미 종료 ---")

 

 

if __name__ == "__main__":

    main()

 

 

https://www.youtube.com/watch?v=5yyDieEdrpg&pp=ygUa7YyM7J207I2sIOqwgOqyqSDslYzrpqzrr7g%3D

 

 

 

 

반응형