본문 바로가기

자동화/Selenium

과거 1달 국내주식 시가총액 순위 자동화로 추출하기

728x90

과거 원하는 1달 국내주식 시가총액 1~50위까지 순위를 자동화로 추출하여 엑셀에 저장하는 코드입니다.

 

시가총액 데이터는 한국거래소 사이트 URL을 통해 데이터를 추출합니다.

http://data.krx.co.kr/contents/MMC/RANK/rank/MMCRANK001.cmd

 

KRX 정보데이터시스템

증권·파생상품의 시장정보(Marketdata), 공매도정보, 투자분석정보(SMILE) 등 한국거래소의 정보데이터를 통합하여 제공 서비스

data.krx.co.kr

 

 

추출하고 싶은 년도 / 월을 콘솔에서 입력 받아 현재 날짜와의 차이를 통해 달력을 이동하여 특정 달 화면으로 이동합니다.

 

input_year = input("년도를 입력하세요. : ")
input_month = input("월을 입력하세요. : ")
driver.find_element(By.CLASS_NAME, 'CI-CAL-OPEN-BTN').click()
time.sleep(2)

cal_text = driver.find_element(By.CLASS_NAME, 'calTit').text #현재 년월 데이터 얻기

year_text = cal_text[:4]
month_text = cal_text[-2:]

year_dif = int(year_text) - int(input_year) #원하는 년도 차이 구하기
month_dif = int(month_text) - int(input_month) #원하는 월 차이 구하기

 

find_elements() a 태그로 추출한 후 원하는 날짜를 클릭할 수 있는 함수를 작성하였습니다. 

 

def date_click(num): #원하는 날 날짜를 설정하는 함수

    if num != 0:
        driver.execute_script('window.scrollTo(0, 0)')
        driver.find_element(By.CLASS_NAME, 'CI-CAL-OPEN-BTN').click()

    cal_date = driver.find_element(By.CLASS_NAME, 'calendarWrap').find_elements(By.TAG_NAME, 'a')

    cal_date[num].click()
    time.sleep(1)
    driver.find_element(By.CLASS_NAME, 'CI-CAL-CONFIRM-BTN').click()
    time.sleep(2)
    driver.find_element(By.ID, 'jsSearchButton').click()
    time.sleep(2)

 

1~50위 순위를 보기 위해서 스크롤 처리가 필요하였는데 페이지 내 표를 따로 스크롤해야 해서 일반적인 방법으로는 실패하였습니다.

 

여러가지 방법을 찾던 중 해당 표를 선택한 후 스크롤을 내리는 방법으로 구현을 선택하였습니다.

ActionChain 내 drag_and_drop 기능을 사용하여 해당 표를 선택한 후 pyautogui 키보드 동작으로 표를 움직일 수 있게 코드를 작성하였습니다.

 

def data_scroll(num): #데이터 추출을 위해 스크롤 처리를 하는 함수
    elements = driver.find_elements(By.CLASS_NAME, 'tui-grid-cell-content')

    drag = elements[35]
    drop = elements[37]

    action.drag_and_drop(drag, drop).perform()
    for i in range(0, num):
        pyautogui.press('down')
    time.sleep(2)

 

표에 있는 데이터를 추출하여 리스트에 저장하는 함수를 작성하였습니다.

 

def data_add(x, y): #추출한 데이터를 추가하는 함수
    elements = driver.find_elements(By.CLASS_NAME, 'tui-grid-cell-content')
    for i in range(x, 38):
        if i % 2 != 0:
            stock_name.append(elements[i].text)

    for i in range(y, 170, 7):
        stock_price.append(elements[i].text)

 

스크롤 함수와 데이터 추가 함수를 반복 사용하여 1일치 1~50위 시가 총액 순위를 추출하는 함수를 작성하였습니다.

 

def daily_data(): #1일치 데이터를 추가하여 엑셀에 저장하는 함수
    stock_name = []
    stock_price = []
    number = 1

    data_add(1, 39)
    data_scroll(19)
    data_add(3, 48)
    data_scroll(14)
    data_add(13, 81)

    wb.create_sheet('test2')
    ws = wb['test2']
    ws.title = driver.find_element(By.ID, 'trdDd').get_attribute('value')  # 시트 타이틀 설정
    ws.append(['순위', '종목', '종가'])  # 첫 행에 저장할 데이터 항목 추가

    for i in range(len(stock_name)):
        ws.append([number, stock_name[i], stock_price[i]])
        number += 1

    wb.save('/Users/user/Desktop/stock.xlsx')  # 해당 경로에 엑셀 파일 저장

 

1달치를 뽑기 위해 1일치 함수를 일자만큼 반복하는 코드를 작성하였습니다.

 

for i in range(len(cal_date)): #해당 월에 있는 일자만큼 반복하여 데이터 추출
    date_click(i)
    daily_data()

 

전체 코드입니다. 해당 코드를 통해 1달치 데이터를 추출하여 엑셀하여 결과를 얻을 수 있습니다.

 

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

input_year = input("년도를 입력하세요. : ")
input_month = input("월을 입력하세요. : ")

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

driver.get('http://data.krx.co.kr/contents/MMC/RANK/rank/MMCRANK001.cmd')
time.sleep(2)
driver.maximize_window() #현재 브라우저 창 최대로 키우기

driver.find_element(By.CLASS_NAME, 'CI-CAL-OPEN-BTN').click()
time.sleep(2)

cal_text = driver.find_element(By.CLASS_NAME, 'calTit').text #현재 년월 데이터 얻기

year_text = cal_text[:4]
month_text = cal_text[-2:]

year_dif = int(year_text) - int(input_year) #원하는 년도 차이 구하기
month_dif = int(month_text) - int(input_month) #원하는 월 차이 구하기

for i in range(year_dif):
    driver.find_element(By.CLASS_NAME, 'prevYear').click()
    time.sleep(1)

for i in range(abs(month_dif)):
    if month_dif > 0:
        driver.find_element(By.CLASS_NAME, 'prevMonth').click()
    else:
        driver.find_element(By.CLASS_NAME, 'nextMonth').click()
    time.sleep(1)

action = ActionChains(driver)

wb = Workbook()  # Workbook 생성

cal_date = driver.find_element(By.CLASS_NAME, 'calendarWrap').find_elements(By.TAG_NAME, 'a')

stock_name = []
stock_price = []


def date_click(num): #원하는 날 날짜를 설정하는 함수

    if num != 0:
        driver.execute_script('window.scrollTo(0, 0)')
        driver.find_element(By.CLASS_NAME, 'CI-CAL-OPEN-BTN').click()

    cal_date = driver.find_element(By.CLASS_NAME, 'calendarWrap').find_elements(By.TAG_NAME, 'a')

    cal_date[num].click()
    time.sleep(1)
    driver.find_element(By.CLASS_NAME, 'CI-CAL-CONFIRM-BTN').click()
    time.sleep(2)
    driver.find_element(By.ID, 'jsSearchButton').click()
    time.sleep(2)


def data_scroll(num): #데이터 추출을 위해 스크롤 처리를 하는 함수
    elements = driver.find_elements(By.CLASS_NAME, 'tui-grid-cell-content')

    drag = elements[35]
    drop = elements[37]

    action.drag_and_drop(drag, drop).perform()
    for i in range(0, num):
        pyautogui.press('down')
    time.sleep(2)


def data_add(x, y): #추출한 데이터를 추가하는 함수
    elements = driver.find_elements(By.CLASS_NAME, 'tui-grid-cell-content')
    for i in range(x, 38):
        if i % 2 != 0:
            stock_name.append(elements[i].text)

    for i in range(y, 170, 7):
        stock_price.append(elements[i].text)


def daily_data(): #1일치 데이터를 추가하여 엑셀에 저장하는 함수
    stock_name = []
    stock_price = []
    number = 1

    data_add(1, 39)
    data_scroll(19)
    data_add(3, 48)
    data_scroll(14)
    data_add(13, 81)

    wb.create_sheet('test2')
    ws = wb['test2']
    ws.title = driver.find_element(By.ID, 'trdDd').get_attribute('value')  # 시트 타이틀 설정
    ws.append(['순위', '종목', '종가'])  # 첫 행에 저장할 데이터 항목 추가

    for i in range(len(stock_name)):
        ws.append([number, stock_name[i], stock_price[i]])
        number += 1

    wb.save('/Users/user/Desktop/stock.xlsx')  # 해당 경로에 엑셀 파일 저장


for i in range(len(cal_date)): #해당 월에 있는 일자만큼 반복하여 데이터 추출
    date_click(i)
    daily_data()

wb.remove(wb['Sheet']) #기존에 있는 Sheet 삭제
wb.save('/Users/user/Desktop/stock.xlsx')

print('Excel Save Complete!!!')

driver.quit()

 

해당 코드를 통해 2022년 2월 시가총액 데이터를 뽑은 결과입니다. 1일마다 시트를 따로 생성하여 데이터를 구분하였습니다.

 

728x90