📌 개념 정리
이 코드는 웹 스크래핑을 통해 특정 키워드(예시로 "슈프림")로 제품 정보를 자동으로 추출하고, 이를 MySQL 데이터베이스에 저장하는 작업을 수행합니다. Selenium과 BeautifulSoup을 사용하여 웹 페이지를 자동으로 조작하고, 데이터를 추출한 뒤, 이를 MySQL에 주기적으로 저장하는 구조입니다.
🚦 동작 원리 및 구조
이 코드는 주로 4가지 주요 부분으로 나눠집니다:
- 웹 드라이버 설정: Selenium을 사용하여 Chrome 브라우저를 자동으로 실행하고, 검색어를 입력하여 결과 페이지를 로드합니다.
- 페이지 스크롤 및 데이터 추출: 스크롤을 내리면서 더 많은 데이터를 로드하고, BeautifulSoup을 이용해 페이지에서 필요한 정보를 추출합니다.
- MySQL 연결 및 데이터 삽입: 추출한 데이터는 MySQL에 저장됩니다.
- 주기적 실행: 프로그램은 24시간 주기로 실행되며, 반복적으로 제품 정보를 수집하고 저장합니다.
💻 코드 예시 및 흐름 분석
1. MySQL 연결 함수
def connect_to_db():
connection = pymysql.connect(
host='127.0.0.1',
user='root',
password='7722',
db='kream',
charset='utf8mb4'
)
return connection
- connect_to_db() 함수는 MySQL 데이터베이스에 연결하는 함수입니다. pymysql.connect() 메서드를 사용하여 데이터베이스에 연결하고, 연결 객체를 반환합니다.
2. 데이터베이스 쿼리 실행 함수
def execute_query(connection, query, args=None):
with connection.cursor() as cursor:
cursor.execute(query, args or ())
if query.strip().upper().startswith("SELECT"):
return cursor.fetchall()
else:
connection.commit()
- execute_query() 함수는 SQL 쿼리를 실행하는 함수입니다. 데이터베이스에 쿼리를 실행하고, SELECT 문일 경우 결과를 반환하며, INSERT, UPDATE, DELETE 쿼리일 경우 commit()을 호출하여 변경 사항을 저장합니다.
3. 크롬 웹드라이버 설정 함수
def setup_driver():
header_user = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
options_ = Options()
options_.add_argument(f"User-Agent={header_user}")
options_.add_experimental_option("detach", True)
options_.add_experimental_option('excludeSwitches', ["enable-logging"])
return webdriver.Chrome(options=options_)
- setup_driver() 함수는 Selenium을 사용하여 Chrome 웹 드라이버를 설정하는 함수입니다. User-Agent를 설정하여 브라우저가 정상적인 사용자 요청처럼 보이도록 하고, 불필요한 로그를 제거하는 옵션을 설정합니다.
4. 검색어 입력 및 페이지 스크롤 함수
def search_product(driver, keyword):
driver.get("https://kream.co.kr/")
time.sleep(1)
# 검색 버튼 클릭
driver.find_element(By.CSS_SELECTOR, ".btn_search.header-search-button.search-button-margin").click()
time.sleep(1.5)
# 검색 입력 필드 찾아서 작업
search_input = driver.find_element(By.CSS_SELECTOR, ".input_search.show_placeholder_on_focus")
search_input.send_keys(keyword)
time.sleep(1)
search_input.send_keys(Keys.ENTER)
# 페이지를 아래로 스크롤하여 더 많은 제품을 로딩
for i in range(20):
driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.PAGE_DOWN)
time.sleep(0.3)
- search_product() 함수는 주어진 keyword로 검색어를 입력하고, 검색 결과 페이지로 이동합니다. PAGE_DOWN 키를 사용하여 페이지를 20번 스크롤하며 더 많은 제품 정보를 로드합니다.
5. 제품 정보 추출 함수
def extract_product_info(soup):
items = soup.select(".item_inner")
product_list = []
for item in items:
product_name = item.select_one(".translated_name").text
if "후드" in product_name:
category = "상의"
brand = item.select_one(".brand-name").text
price = item.select_one(".amount").text
# 데이터 리스트에 추가
product_info = [category, brand, product_name, price]
product_list.append(product_info)
return product_list
- extract_product_info() 함수는 BeautifulSoup을 사용하여 HTML에서 제품 정보를 추출합니다. translated_name 클래스를 통해 제품명을 가져오고, "후드"라는 단어가 포함된 제품만 필터링하여 카테고리, 브랜드, 가격을 추출합니다.
6. MySQL에 제품 데이터를 삽입하는 함수
def insert_into_db(connection, product_list):
for i in product_list:
query = "INSERT INTO KREAM (category, brand, product_name, price) VALUES (%s, %s, %s, %s)"
execute_query(connection, query, i)
- insert_into_db() 함수는 추출된 제품 정보를 MySQL 데이터베이스의 KREAM 테이블에 삽입하는 함수입니다. execute_query()를 통해 파라미터화된 INSERT INTO 쿼리를 실행합니다.
7. 메인 함수
def main():
keyword = "슈프림" # 예시로 고정된 키워드 사용
# WebDriver 설정
driver = setup_driver()
# 제품 검색
search_product(driver, keyword)
# HTML 소스 코드 가져오기
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")
# 제품 정보 추출
product_list = extract_product_info(soup)
# MySQL 연결
connection = connect_to_db()
# 제품 정보를 MySQL에 삽입
insert_into_db(connection, product_list)
# 드라이버 종료
driver.quit()
- main() 함수는 전체 프로그램의 실행 흐름을 제어합니다. 검색어를 설정하고, 제품을 검색하여 HTML을 파싱한 후, MySQL에 데이터를 삽입합니다.
8. 주기적 실행 함수
def run_periodically():
execution_interval = 86400 # 86400초 = 24시간
while True:
try:
# 스크래핑 함수 호출
main() # 메인 스크래핑 작업 실행
print("작업이 완료되었습니다. 24시간 후에 다시 실행됩니다.")
time.sleep(execution_interval) # 24시간 대기
except Exception as e:
print(f"에러 발생: {e}")
time.sleep(60) # 에러 발생 시 1분 후 재시도
- run_periodically() 함수는 프로그램을 24시간마다 주기적으로 실행하는 함수입니다. main() 함수가 정상적으로 완료되면 24시간 대기 후 다시 실행되고, 에러가 발생하면 1분 후에 재시도합니다.
9. 최종코드
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time
import pymysql
# MySQL 연결 함수
def connect_to_db():
connection = pymysql.connect(
host='127.0.0.1',
user='root',
password='7722',
db='kream',
charset='utf8mb4'
)
return connection
# 데이터베이스 쿼리 실행 함수
def execute_query(connection, query, args=None):
with connection.cursor() as cursor:
cursor.execute(query, args or ())
if query.strip().upper().startswith("SELECT"):
return cursor.fetchall()
else:
connection.commit()
# 크롬 웹드라이버를 설정하는 함수
def setup_driver():
header_user = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
options_ = Options()
options_.add_argument(f"User-Agent={header_user}")
options_.add_experimental_option("detach", True) # 브라우저 종료되지 않게 설정
options_.add_experimental_option('excludeSwitches', ["enable-logging"]) # 불필요한 로그 제거
return webdriver.Chrome(options=options_)
# 검색어를 입력하고, 페이지를 다운스크롤하는 함수
def search_product(driver, keyword):
driver.get("https://kream.co.kr/")
time.sleep(1)
# 검색 버튼 클릭
driver.find_element(By.CSS_SELECTOR, ".btn_search.header-search-button.search-button-margin").click()
time.sleep(1.5)
# 검색 입력 필드 찾아서 작업
search_input = driver.find_element(By.CSS_SELECTOR, ".input_search.show_placeholder_on_focus")
search_input.send_keys(keyword)
time.sleep(1)
search_input.send_keys(Keys.ENTER)
# 페이지를 아래로 스크롤하여 더 많은 제품을 로딩
for i in range(20):
driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.PAGE_DOWN)
time.sleep(0.3)
# 제품 정보를 추출하는 함수
def extract_product_info(soup):
items = soup.select(".item_inner")
product_list = []
for item in items:
product_name = item.select_one(".translated_name").text
if "후드" in product_name:
category = "상의"
brand = item.select_one(".brand-name").text
price = item.select_one(".amount").text
# 데이터 리스트에 추가
product_info = [category, brand, product_name, price]
product_list.append(product_info)
return product_list
# MySQL에 제품 데이터를 삽입하는 함수
def insert_into_db(connection, product_list):
for i in product_list:
# 파라미터화된 쿼리로 변경
query = "INSERT INTO KREAM (category, brand, product_name, price) VALUES (%s, %s, %s, %s)"
execute_query(connection, query, i)
# 메인 함수
def main():
# 검색어 입력 받기
keyword = "슈프림" # 예시로 고정된 키워드 사용
# WebDriver 설정
driver = setup_driver()
# 제품 검색
search_product(driver, keyword)
# HTML 소스 코드 가져오기
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")
# 제품 정보 추출
product_list = extract_product_info(soup)
# MySQL 연결
connection = connect_to_db()
# 제품 정보를 MySQL에 삽입
insert_into_db(connection, product_list)
# 드라이버 종료
driver.quit()
# 주기적인 실행 설정: 24시간마다 실행
def run_periodically():
execution_interval = 86400 # 86400초 = 24시간
while True:
try:
# 스크래핑 함수 호출
main() # 메인 스크래핑 작업 실행
print("작업이 완료되었습니다. 24시간 후에 다시 실행됩니다.")
time.sleep(execution_interval) # 24시간 대기
except Exception as e:
print(f"에러 발생: {e}")
time.sleep(60) # 에러 발생 시 1분 후 재시도
if __name__ == "__main__":
run_periodically()
🧪 실전 사례
이 코드는 e-commerce 사이트에서 자동으로 제품 정보를 스크래핑하고, MySQL 데이터베이스에 저장하는 방식으로, 예를 들어, 매일 최신 제품 정보를 자동으로 수집하여 업데이트할 수 있습니다.
🧠 고급 팁 or 자주 하는 실수
- 팁: 주기적으로 데이터를 수집하는 경우, 스크래핑 대상 웹사이트의 robots.txt 규정을 확인하여 웹사이트의 스크래핑 정책을 준수해야 합니다.
- 실수: MySQL 삽입 시, 데이터의 중복 삽입을 방지하려면 ON DUPLICATE KEY UPDATE 구문을 사용하는 것이 좋습니다.
✅ 마무리 요약 및 복습 포인트
- 이 코드는 주기적인 데이터 수집 자동화를 구현하는 예시로, Selenium과 BeautifulSoup을 사용하여 웹 데이터를 추출하고, 이를 MySQL 데이터베이스에 저장하는 방식입니다.
- 주기적인 실행을 위한 로직과 오류 처리, 파라미터화된 SQL 쿼리를 사용하여 데이터베이스에 안전하게 삽입하는 부분이 핵심입니다.
'프로젝트' 카테고리의 다른 글
Flask API 프로젝트: 게시글 조회 및 작성 API(jsonify) (0) | 2025.04.18 |
---|---|
Flask와 Jinja 템플릿 활용 프로젝트 (0) | 2025.04.17 |
Chapter 3 Kream 크롤링, 웹스크래핑 프로젝트(데이터베이스,MySQL) (0) | 2025.04.16 |
Chapter 3 Kream 크롤링, 웹스크래핑 프로젝트 (0) | 2025.04.16 |
Chapter 2 네이버 동적 스크랩핑,크롤러 프로젝트 (0) | 2025.04.15 |