본문 바로가기

자동화/Selenium

주요 서점 주간 베스트 20위까지 데이터 엑셀에 자동화로 저장하기

728x90

종종 인터넷에서 책을 구매할 때 사이트별로 베스트셀러 순위를 자주 확인합니다. (인기있는 책을 먼저 읽어보는 걸 좋아합니다.)

 

베스트셀러를 살펴보면 주요 사이트 별로 비슷하거나 다른 경우도 많은데요.

가끔씩 보다가 해당 데이터를 공부도 할겸 자동화로 뽑아보면 재밌을 거 같아서 구현해보았습니다.

 

데이터는 주간 베스트 20위까지 데이터를 뽑아보고 사이트는 교보문고, 영풍문고, yes24, 알라딘 주요 서점 사이트 4곳으로 선정하였습니다.

 

서점별로 각 엑셀 시트에 저장하기 위해 서점 제목으로 시트를 각각 생성하였습니다.

 

# Workbook 생성
wb = Workbook()

# 서점별 시트 생성
wb.create_sheet(index=0, title="교보문고")
wb.create_sheet(index=1, title="영풍문고")
wb.create_sheet(index=2, title="yes24")
wb.create_sheet(index=3, title="알라딘")

 

데이터를 저장할 시트를 선택한 후 추가할 데이터 항목이 무엇인지 추가하였습니다.

 

# 저장할 시트 선택 후 첫 행에 저장할 데이터 항목 추가
ws = wb["교보문고"]
ws.append(['순위', '제목', '가격', '저자'])

 

서점마다 코드가 달라서 구현 난이도가 달랐는데요. 교보문고와 영풍문고는 CLASS_NAME이 있어서

find_elements > CLASS_NAME 코드 형태로 작성하여 데이터를 저장하였습니다.

 

# 제목, 가격, 저자 데이터 추출
name = driver.find_elements(By.CLASS_NAME, 'prod_name')
price = driver.find_elements(By.CLASS_NAME, 'price')
author = driver.find_elements(By.CLASS_NAME, 'prod_author')

# 엑셀에 데이터 저장
for i in range(0, 20):
    ws.append([i+1, name[i].text, price[i].text, author[i].text])

 

yes24의 경우 가격과 저자는 CLASS_NAME으로 구현이 가능했는데 제목이 CLASS_NAME이 없었습니다.

 

추출할 데이터 내 class_name이 존재하지 않는 경우

 

그로 인해 상위 CLASS_NAME을 기준으로 find_elements > TAG_NAME 형태로 구현하여 데이터를 저장하였습니다.

 

name = driver.find_elements(By.CLASS_NAME, 'goodsTxtInfo')
price = driver.find_elements(By.CLASS_NAME, 'priceB')
author = driver.find_elements(By.CLASS_NAME, 'aupu')

for i in range(0, 20):
    ws.append([i+1, name[i].find_elements(By.TAG_NAME, 'a')[0].text, price[i].text, author[i].text])

 

알라딘의 경우에는 가격은 다른 사이트와 동일하였으나 제목과 저자의 경우 CLASS_NAME이 존재하지 않고 상위 CLASS_NAME도 다른 코드에서 사용하기 때문에 제목, 저자 항목과 가격 항목을 구분하여 코드를 작성하였습니다.

 

하나의 책 리스트에 동일한 class_name 사용하는 경우

 

name = driver.find_elements(By.CLASS_NAME, 'ss_book_list')
price = driver.find_elements(By.CLASS_NAME, 'ss_p2')

 

for i in range(0, 20):
    book_list1.append([i+1, price[i].text])

for i in range(0, 40, 2):
    book_list2.append([name[i].find_elements(By.TAG_NAME, 'a')[1].text, name[i].find_elements(By.TAG_NAME, 'li')[2].text])

 

2개의 리스트를 map을 이용하여 합친 이후 리스트 순서가 다른 사이트와 동일하게 순위, 제목, 가격, 저자 형태로 나오게 하기 위해 

제목과 가격 위치를 변경한 후 엑셀에 저장하였습니다.

 

# 2개 리스트 2차원 형태로 merge
merge_list = list(map(list.__add__, book_list1, book_list2))

# 데이터 위치 swap 후 엑셀에 저장
for data in merge_list:
    data[1], data[2] = data[2], data[1]
    ws.append(data)

 

엑셀 파일 생성시 기존에 있던 Sheet 시트는 필요하지 않아 제거하였습니다.

 

# 기존에 있는 불필요한 시트 삭제
del wb['Sheet']

 

전체 소스 코드입니다.

해당 코드 실행시 각 서점별 주간 베스트 20위까지 데이터를 추출하여 엑셀에 저장한 결과를 얻을 수 있습니다.

 

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
import time
from openpyxl import Workbook

# Workbook 생성
wb = Workbook()

# 서점별 시트 생성
wb.create_sheet(index=0, title="교보문고")
wb.create_sheet(index=1, title="영풍문고")
wb.create_sheet(index=2, title="yes24")
wb.create_sheet(index=3, title="알라딘")

# 저장할 시트 선택 후 첫 행에 저장할 데이터 항목 추가
ws = wb["교보문고"]
ws.append(['순위', '제목', '가격', '저자'])

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get('https://product.kyobobook.co.kr/bestseller/total?period=002#?page=1&per=20&period=002&ymw=&bsslBksClstCode=A')
time.sleep(5)

# 제목, 가격, 저자 데이터 추출
name = driver.find_elements(By.CLASS_NAME, 'prod_name')
price = driver.find_elements(By.CLASS_NAME, 'price')
author = driver.find_elements(By.CLASS_NAME, 'prod_author')

# 엑셀에 데이터 저장
for i in range(0, 20):
    ws.append([i+1, name[i].text, price[i].text, author[i].text])

ws = wb["영풍문고"]
ws.append(['순위', '제목', '가격', '저자'])

driver.get('https://www.ypbooks.co.kr/book_arrange.yp?targetpage=book_week_best&pagetype=5&depth=1')
time.sleep(5)

name = driver.find_elements(By.CLASS_NAME, 'boxiconset_bk_tt')
price = driver.find_elements(By.CLASS_NAME, 'orange')
author = driver.find_elements(By.CLASS_NAME, 'nbookName')

for i in range(0, 20):
    print()
    ws.append([i+1, name[i].text, price[i].text + "원", author[i].text])

ws = wb["yes24"]
ws.append(['순위', '제목', '가격', '저자'])

driver.get('http://www.yes24.com/24/category/bestseller?CategoryNumber=001&sumgb=08')
time.sleep(5)

name = driver.find_elements(By.CLASS_NAME, 'goodsTxtInfo')
price = driver.find_elements(By.CLASS_NAME, 'priceB')
author = driver.find_elements(By.CLASS_NAME, 'aupu')

for i in range(0, 20):
    ws.append([i+1, name[i].find_elements(By.TAG_NAME, 'a')[0].text, price[i].text, author[i].text])

ws = wb["알라딘"]
ws.append(['순위', '제목', '가격', '저자'])

driver.get('https://www.aladin.co.kr/shop/common/wbest.aspx?BranchType=1&BestType=Bestseller')
time.sleep(5)

name = driver.find_elements(By.CLASS_NAME, 'ss_book_list')
price = driver.find_elements(By.CLASS_NAME, 'ss_p2')

book_list1 = []
book_list2 = []
merge_list = []

for i in range(0, 20):
    book_list1.append([i+1, price[i].text])

for i in range(0, 40, 2):
    book_list2.append([name[i].find_elements(By.TAG_NAME, 'a')[1].text, name[i].find_elements(By.TAG_NAME, 'li')[2].text])

# 2개 리스트 2차원 형태로 merge
merge_list = list(map(list.__add__, book_list1, book_list2))

# 데이터 위치 swap 후 엑셀에 저장
for data in merge_list:
    data[1], data[2] = data[2], data[1]
    ws.append(data)

# 기존에 있는 불필요한 시트 삭제
del wb['Sheet']

wb.save('/Users/user/Desktop/bookchart.xlsx')
print('Excel 저장을 완료하였습니다.')

driver.close()

 

코드 실행 후 저장된 엑셀 파일 실행 결과

728x90