프로젝트

Chapter 3 Kream 크롤링, 웹스크래핑 프로젝트(데이터베이스,MySQL)

Chansman 2025. 4. 16. 14:57

📌 개념 정리

이 코드는 웹 스크래핑을 통해 네이버의 특정 쇼핑몰 웹사이트에서 제품 정보를 자동으로 추출하고, 이를 MySQL 데이터베이스에 저장하는 과정입니다. Selenium을 사용하여 웹 브라우저를 자동화하고, BeautifulSoup을 이용해 HTML을 파싱한 뒤, 추출한 데이터는 MySQL 데이터베이스의 테이블에 삽입됩니다.

🚦 동작 원리 및 구조

이 코드는 다음과 같은 주요 흐름을 따릅니다:

  1. 검색어 입력 및 URL 생성: 사용자가 입력한 검색어를 바탕으로 네이버의 특정 쇼핑몰 URL을 동적으로 생성합니다.
  2. 웹 브라우저 자동화: Selenium을 사용하여 웹 브라우저를 자동으로 실행하고, 검색어를 입력하여 제품 리스트를 로드합니다.
  3. 스크롤 및 페이지 소스 추출: 페이지를 스크롤하여 필요한 데이터를 모두 로드하고, HTML 소스를 추출합니다.
  4. 데이터 파싱 및 필터링: BeautifulSoup을 사용하여 HTML에서 특정 제품 정보를 추출하고, 조건에 맞는 제품만 필터링하여 리스트에 저장합니다.
  5. MySQL 연결 및 데이터 저장: 추출된 데이터를 MySQL 데이터베이스에 삽입합니다.

💻 코드 예시 및 흐름 분석

아래는 코드의 주요 부분과 그 흐름을 상세히 설명합니다.

1. 필요한 라이브러리 및 패키지 불러오기

import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time  # 파이썬 기본 패키지
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import pymysql
  • requests: HTTP 요청을 보내는 라이브러리입니다. 이 코드에서는 사용되지 않지만, 보통 웹 스크래핑 시 HTTP 요청을 보낼 때 사용됩니다.
  • selenium: 웹 브라우저를 자동으로 제어하는 라이브러리입니다.
  • BeautifulSoup: HTML 소스를 파싱하여 필요한 데이터를 추출하는 데 사용됩니다.
  • time: 코드 실행 중 잠시 멈추기 위해 사용됩니다.
  • pymysql: MySQL 데이터베이스와의 연결을 위한 라이브러리입니다.

2. 검색어 입력 및 URL 생성

keyword = input("검색을 원하시는 브랜드 또는 제품명을 입력해주세요 : ")
url = "https://kream.co.kr/"
  • 사용자로부터 검색어를 입력받고, 이 검색어를 바탕으로 특정 쇼핑몰 페이지를 동적으로 생성합니다.

3. 웹 드라이버 옵션 설정

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"])
  • User-Agent를 설정하여 브라우저의 요청이 정상적인 사용자로부터 오는 것처럼 보이도록 합니다.
  • detach 옵션은 브라우저를 종료하지 않고 계속 유지되도록 설정합니다.
  • excludeSwitches는 불필요한 로그 출력을 없애는 설정입니다.

4. 웹 브라우저 실행 및 네이버 접속

driver = webdriver.Chrome(options=options_)
driver.get(url)
time.sleep(1)
  • Selenium을 사용하여 설정한 옵션을 적용한 Chrome 브라우저를 실행하고, 지정한 URL로 접속합니다.

5. 검색어 입력 및 Enter 키 누르기

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)
  • Selenium을 통해 검색 입력 필드를 찾아 사용자가 입력한 키워드를 입력하고, Enter 키를 눌러 검색을 실행합니다.

6. 페이지 스크롤하여 데이터 로드

for i in range(20):
    driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.PAGE_DOWN)
    time.sleep(0.3)
  • PAGE_DOWN 키를 사용하여 페이지를 20번 스크롤하여 더 많은 제품 정보를 로드합니다. 이 방식은 동적 로딩되는 제품들을 모두 로드하는 데 유용합니다.

7. HTML 파싱 및 제품 정보 추출

html = driver.page_source
soup = BeautifulSoup(html, "html.parser")

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)  # 리스트에 제품 정보 추가
  • BeautifulSoup을 사용하여 HTML 소스를 파싱하고, 각 제품 항목을 추출합니다.
  • 제품명에 "후드"가 포함된 항목만 필터링하여 카테고리, 브랜드, 제품명, 가격을 추출하고 product_list에 저장합니다.

8. MySQL 데이터베이스 연결 및 데이터 삽입

connection = pymysql.connect(
    host = '127.0.0.1',
    user = 'root',
    password = '7722',
    db = 'kream',
    charset = 'utf8mb4'
)

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()

for i in product_list:
    query = "INSERT INTO KREAM (category, brand, product_name, price) VALUES (%s, %s, %s, %s)"
    execute_query(connection, query, i)
  • pymysql을 사용하여 MySQL 데이터베이스에 연결합니다.
  • execute_query 함수는 SQL 쿼리를 실행하는 함수로, 데이터를 삽입하기 위해 INSERT INTO 쿼리를 사용합니다.
  • product_list의 각 항목을 데이터베이스의 KREAM 테이블에 삽입합니다.

9. 브라우저 종료

driver.quit()
  • Selenium을 사용하여 작업이 끝난 후 브라우저를 종료합니다.

10. 함수를 이용해서 코드 리팩토링 

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 create_connection():
    return pymysql.connect(
        host='127.0.0.1',
        user='root',
        password='7722',
        db='kream',
        charset='utf8mb4'
    )

# 쿼리 실행 함수
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

# 메인 함수
def main():
    # 검색어 입력 받기
    keyword = input("검색을 원하시는 브랜드 또는 제품명을 입력해주세요 : ")

    # 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 = create_connection()

    # 데이터베이스에 삽입
    for product in product_list:
        query = "INSERT INTO KREAM (category, brand, product_name, price) VALUES (%s, %s, %s, %s)"
        execute_query(connection, query, product)

    # 커넥션 닫기
    connection.close()

    # 드라이버 종료
    driver.quit()

if __name__ == "__main__":
    main()

🧪 실전 사례

이 코드는 실제로 e-commerce 사이트에서 실시간으로 제품 정보를 추출하고, 이를 MySQL 데이터베이스에 저장하는 자동화된 데이터 수집 시스템의 예입니다. 예를 들어, 사용자가 "후드"라는 키워드를 검색하고, 해당 검색 결과에서 관련 제품의 브랜드, 가격 등을 데이터베이스에 저장할 수 있습니다.

🧠 고급 팁 or 자주 하는 실수

  • : Selenium을 사용할 때 페이지가 동적으로 로드되는 경우 time.sleep()을 이용해 충분히 기다린 후 페이지가 완전히 로드되도록 해야 합니다.
  • 실수: pymysql로 쿼리를 실행할 때, SQL 인젝션 공격을 방지하기 위해 파라미터화된 쿼리를 사용해야 합니다. execute_query 함수에서 이를 안전하게 처리하는 방식으로 작성되었습니다.

✅ 마무리 요약 및 복습 포인트

  • 이 코드는 웹 스크래핑을 통해 특정 사이트에서 제품 정보를 자동으로 추출하고, 이를 MySQL 데이터베이스에 저장하는 작업을 수행합니다.
  • 중요한 포인트는 Selenium을 사용하여 브라우저 자동화를 수행하고, BeautifulSoup을 이용하여 HTML을 파싱하여 원하는 데이터를 추출하는 것입니다.
  • 또한, MySQL을 이용하여 추출한 데이터를 데이터베이스에 안전하게 저장하는 과정도 포함되어 있습니다.