기술블로그
📌 MySQL 데이터베이스 정리 (with 크롤링 in Selenium, PymySQL)
Chansman
2025. 3. 25. 14:10

📌 개념 정리
이번 포스팅에서는 Python과 Selenium을 이용하여 웹에서 책 정보를 크롤링하고 PyMySQL을 통해 MySQL 데이터베이스에 저장하는 과정을 프로세스별로 세부적으로 정리합니다.
🚦 전체 프로세스 흐름 및 구조
이 작업은 다음과 같은 순서로 진행됩니다:
- MySQL 연결 → 2. 웹 페이지 접속 → 3. 데이터 추출 → 4. 데이터 정제 및 변환 → 5. 예외 처리 → 6. MySQL 저장 → 7. 반복 및 지연
각 프로세스를 단계별로 설명합니다.
💻 프로세스별 코드 흐름 설명
import pymysql
import time
import re
from datetime import datetime
# MySQL 데이터베이스 연결 설정
conn = pymysql.connect(
host='localhost',
user='root',
password='7722',
db='yes24',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
with conn.cursor() as cur:
for link in link_list:
# 웹 페이지로 이동
browser.get(link)
# 기본 정보 추출
title = browser.find_element(By.CLASS_NAME, 'gd_name').text
author = browser.find_element(By.CLASS_NAME, 'gd_auth').text
publisher = browser.find_element(By.CLASS_NAME, 'gd_pub').text
# 출간일 데이터를 YYYY-MM-DD 형태로 변환
publishing = browser.find_element(By.CLASS_NAME, 'gd_date').text
match = re.search(r'(\d+)년 (\d+)월 (\d+)일', publishing)
if match:
year, month, day = match.groups()
data_obj = datetime(int(year), int(month), int(day))
publishing = data_obj.strftime("%Y-%m-%d")
else:
publishing = "2023-01-01" # 예외 발생 시 기본값 지정
# 평점 데이터 처리 (숫자 변환 및 예외 처리)
rating_text = browser.find_element(By.CLASS_NAME, 'yes_b').text.strip()
if rating_text == '':
rating = 0.0
else:
try:
rating = float(rating_text)
except ValueError:
rating = 0.0
# 리뷰 개수 처리 (콤마 제거 및 숫자 변환)
review_text = browser.find_element(By.CLASS_NAME, 'txC_blue').text.replace(",", "")
try:
review = int(review_text)
except ValueError:
review = 0
# 판매량 데이터 처리 (콤마 제거 및 숫자 변환)
sales = browser.find_element(By.CLASS_NAME, 'gd_sellNum').text.split(" ")[2]
sales = int(sales.replace(",", ""))
# 가격 데이터 처리 (콤마 및 단위 제거 후 숫자 변환)
price = browser.find_element(By.CLASS_NAME, 'yes_m').text[:-1]
price = int(price.replace(",", ""))
# 순위 데이터 추출 및 예외 처리
gd_best_text = browser.find_element(By.CLASS_NAME, 'gd_best').text
# 순위(ranking) 추출
try:
ranking = gd_best_text.split(" | ")[0].split(" ")[2][:-1]
except IndexError:
ranking = "0"
# 순위 유지 주간(ranking_weeks) 추출
try:
ranking_weeks = gd_best_text.split(" | ")[1].split(" ")[2][:-1]
except IndexError:
ranking_weeks = 0
# MySQL 데이터베이스에 저장
sql = '''
INSERT INTO Books(
title, author, publisher, publishing, rating, review, sales, price, ranking, ranking_weeks
)
VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
'''
cur.execute(sql, (title, author, publisher, publishing, rating, review, sales, price, ranking, ranking_weeks))
conn.commit()
# 페이지 요청 간격 유지
time.sleep(2)
✅ Step 1: MySQL 연결
conn = pymysql.connect(
host='localhost',
user='root',
password='7722',
db='yes24',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
- 로컬 MySQL DB에 연결하여 데이터 저장 준비를 합니다.
- 한글 데이터를 위해 charset을 utf8mb4로 지정합니다.
✅ Step 2: 웹 페이지 접속
for link in link_list:
browser.get(link)
- 반복문을 이용하여 크롤링할 각 페이지로 이동합니다.
✅ Step 3: 데이터 추출 (HTML 클래스 기반)
title = browser.find_element(By.CLASS_NAME, 'gd_name').text
author = browser.find_element(By.CLASS_NAME, 'gd_auth').text
publisher = browser.find_element(By.CLASS_NAME, 'gd_pub').text
- Selenium을 이용하여 웹 페이지에서 책의 제목, 저자, 출판사 정보를 클래스명을 기준으로 가져옵니다.
✅ Step 4: 데이터 정제 및 변환
출판일 데이터 변환
publishing = browser.find_element(By.CLASS_NAME, 'gd_date').text
match = re.search(r'(\d+)년 (\d+)월 (\d+)일', publishing)
if match:
year, month, day = match.groups()
data_obj = datetime(int(year), int(month), int(day))
publishing = data_obj.strftime("%Y-%m-%d")
else:
publishing = "2023-01-01"
- 출간일은 'YYYY년 MM월 DD일' 형식에서 YYYY-MM-DD 형식으로 변환합니다.
- 형식이 맞지 않으면 기본값(2023-01-01)으로 저장합니다.
평점 데이터 처리
rating_text = browser.find_element(By.CLASS_NAME, 'yes_b').text.strip()
if rating_text == '':
rating = 0.0
else:
try:
rating = float(rating_text)
except ValueError:
rating = 0.0
- 평점 텍스트를 숫자로 변환합니다.
- 데이터가 없거나 숫자가 아닌 경우 0.0으로 저장합니다.
리뷰 개수 처리
review_text = browser.find_element(By.CLASS_NAME, 'txC_blue').text.replace(",", "")
try:
review = int(review_text)
except ValueError:
review = 0
- 리뷰 개수에서 콤마를 제거한 뒤 숫자로 변환합니다.
- 숫자가 아닌 경우 0으로 처리합니다.
판매량 데이터 처리
sales = browser.find_element(By.CLASS_NAME, 'gd_sellNum').text.split(" ")[2]
sales = int(sales.replace(",", ""))
- 판매량에서 콤마를 제거하고 숫자로 변환합니다.
가격 데이터 처리
price = browser.find_element(By.CLASS_NAME, 'yes_m').text[:-1]
price = int(price.replace(",", ""))
- 가격에서 '원' 단위를 제거하고 콤마를 삭제하여 숫자 값으로 변환합니다.
✅ Step 5: 순위 데이터 추출 및 예외 처리
순위(ranking)
gd_best_text = browser.find_element(By.CLASS_NAME, 'gd_best').text
try:
ranking = gd_best_text.split(" | ")[0].split(" ")[2][:-1]
except IndexError:
ranking = "0"
- 베스트셀러 순위를 추출하며 데이터 형식이 다른 경우 예외 처리를 통해 0으로 처리합니다.
순위 유지 주간(ranking_weeks)
try:
ranking_weeks = gd_best_text.split(" | ")[1].split(" ")[2][:-1]
except IndexError:
ranking_weeks = 0
- 순위 유지 기간을 추출하며 예외가 발생하면 기본값을 0으로 저장합니다.
✅ Step 6: MySQL 데이터베이스에 저장
sql = '''
INSERT INTO Books(
title, author, publisher, publishing, rating, review, sales, price, ranking, ranking_weeks
)
VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
'''
cur.execute(sql, (title, author, publisher, publishing, rating, review, sales, price, ranking, ranking_weeks))
conn.commit()
- 추출한 모든 데이터를 MySQL의 Books 테이블에 저장합니다.
- commit()을 통해 DB에 변경사항을 적용합니다.
✅ Step 7: 페이지 요청 간격 유지
time.sleep(2)
- 웹사이트 서버에 과부하를 주지 않고, IP차단 등을 방지하기 위해 각 요청마다 2초간 지연을 줍니다.
🧪 실전 사례
- 도서 정보를 자동 수집하여 주간 베스트셀러 분석 시스템에 활용 가능
- 가격 및 판매량 추이를 추적하여 마케팅 자료로 활용 가능
🧠 고급 팁 및 자주 하는 실수
✔️ 고급 팁
- WebDriverWait를 활용해 동적 페이지의 로딩 문제를 해결할 수 있습니다.
- 데이터 저장 시 bulk insert를 활용하면 성능을 높일 수 있습니다.
❌ 자주 하는 실수
- 데이터 정제 과정에서 예외 처리를 놓치는 경우가 많으므로, 항상 try-except를 이용하여 코드의 견고성을 높이세요.
- SQL 컬럼명이나 데이터 타입이 불일치하여 오류가 발생할 수 있으니 주의가 필요합니다.
✅ 마무리 요약 및 복습 포인트
- 웹 페이지에서 데이터를 추출하고 MySQL에 저장하는 전체 과정을 세부적으로 살펴보았습니다.
- 각 단계별로 데이터의 정확성과 안정성을 높이기 위한 다양한 처리 방법을 적용하였습니다.
- 이 프로세스는 실무에서도 바로 활용 가능한 구조입니다. 본 가이드를 참고하여 자신의 크롤링 시스템을 더욱 효과적으로 구성해 보세요! 🚀