GIL's LAB

[예제 2] 전종목 주가 데이터 다운로드 본문

파이썬/업무 자동화

[예제 2] 전종목 주가 데이터 다운로드

GIL~ 2022. 1. 11. 15:13

문제

KRX 정보데이터시스템에서 특정 기간 동안의 일별 전종목 시세 데이터를 다운로드하려 합니다. 

이 시스템에서 주가 데이터는 다음과 같은 절차로 다운로드할 수 있습니다.

(1) 조회일자 입력

(2) 조회 버튼 클릭

(3) 다운로드 버튼 클릭

(4) csv 버튼 클릭 (상황에 맞게 Excel 버튼 클릭도 가능)

(5) 필요에 따라 파일명 수정

 

한 데이터를 조회하고 다운로드하는데 약 30초 가까이 소요되며, 데이터가 많을수록 반복적이고 귀찮은 일입니다. 

설명을 위해 2020년 12월 1일부터 4일까지의 데이터를 수집하는 예제를 살펴보겠습니다.

 

환경 세팅: 셀레니움

셀레니움을 사용해서 데이터를 수집하려면 셀레니움 패키지와 웹 드라이버를 설치해야 합니다.

셀레니움은 아나콘다 프롬프트에 아래와 같은 명령어를 입력하여 설치할 수 있습니다.

$ pip install selenium

웹 드라이버는 종류가 많지만, 여기서는 크롬 웹 드라이버를 사용하겠습니다. 크롬 웹 드라이버는 이 링크에서 아래와 같이 다운로드받을 수 있습니다. 

크롬 버전은 우측 상단의 더보기 버튼을 클릭하고 [도움말]→ [Chrome 정보]를 클릭하면 확인할 수 있습니다.

참고로 64비트를 사용하는 사용자도 웹 드라이버는 32비트버전을 설치해야 합니다 (애초에 그 파일밖에없습니다).

다운로드 한 압축 파일을 풀어서 chromedriver.exe 파일을 우리가 데이터를 수집할 경로로 이동하겠습니다 (사실 어디에 두더라도 경로만 잘 설정하면 상관없습니다).

 

파이썬 코드

기본 설정

이제 파이썬 코드를 이용하여 전종목 주가 데이터를 다운로드하여 정리해보겠습니다. 

먼저, 필요한 모듈을 모두 불러오겠습니다.

# 모듈 불러오기
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import os

다음으로 데이터를 수집할 날짜 목록을 YYYYMMDD 꼴로 정의하고, 데이터가 다운로드되는 경로(보통 Downloads 폴더)와 다운로드된 데이터를 옮길 경로를 정의하겠습니다.

date_list = ["20201201", "20201202", "20201203", "20201204"]
download_folder_path = r"C:\Users\Gilseung\Downloads"
file_path = r"C:\Users\Gilseung\Desktop\전종목시세데이터수집"
before_file_list = set(os.listdir(download_folder_path))

YYYYMMDD꼴로 정의한 이유는 KRX에서 사용하는 날짜 형식 체계이기 때문입니다. 위 코드의 마지막 줄은 새로 다운로드받은 데이터를 식별하기 위해 현재 다운로드 폴더에 있는 파일 목록을 집합으로 바꿔서 before_file_list에 저장한 것입니다. 

 

웹 페이지 분석

이제 셀레니움을 이용하여 웹 페이지에 접속하겠습니다. 앞서 다운로드받은 chromedriver.exe를 입력으로 하여 driver를 정의해줍니다. 단, 파일명만 입력한 이유는 현재 작성중인 소스 코드와 드라이버가 같은 위치에 있기 때문입니다. 만약 다른 위치에 있다면 경로까지 같이 입력해줘야 합니다.

driver = webdriver.Chrome("chromedriver.exe")

이제 get 메서드를 이용하여 url에 접속하겠습니다.

url = "http://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC0201020101"
driver.get(url)
WebDriverWait(driver, 10000).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'loading-bar-overlay')))

마지막 줄은 class 이름이 loading-bar-overlay인 엘리먼트가 보이지 않을 때까지 드라이버를 멈춘다는 뜻입니다. 이 엘리먼트가 무엇인지 url에 직접 접속하여 확인해보겠습니다.

아래와 같이 url에 접속하거나 조회버튼을 클릭하면 "데이터를 생성중입니다. 잠시만 기다려 주십시오"라는 메시지와 함께 아무런 데이터가 표출되지 않습니다. 

이때, 이 부분을 마우스 우클릭해서 검사 버튼을 클릭해보면 해당 태그가 <div class="loading-bar-overlay">임을 알 수 있습니다. 이 태그가 뜨지 않을 때까지 기다린 것입니다.

이제 날짜를 입력하는 엘리먼트와 조회버튼 엘리먼트를 나타내는 태그를 검사해보겠습니다. 각 엘리먼트를 나타내는 부분을 마우스 우클릭해서 검사 버튼을 클릭하면 아래와 같은 태그임을 알 수 있습니다.

 

날짜 입력 

<input type="text" name="trdDd" id="trdDd" value="20220111" maxlength="8">

 

조회버튼

<a href="javascript:void(0);" class="btn_black btn_component_search" name="search" id="jsSearchButton">조회</a>

 

두 태그 모두 id가 있으므로, id를 기준으로 엘리먼트를 찾겠습니다.

date_element = driver.find_element(By.ID, "trdDd")
search_button = driver.find_element(By.ID, "jsSearchButton")

이제 date_list를 순회하면서 데이터를 다운로드하겠습니다. 설명을 위해 라인 번호를 추가했습니다.

 1 for date in date_list:
 2     print(date)
 3     date_element.click()
 4     driver.execute_script("arguments[0].value = '{}'".format(date), date_element)
 5     search_button.click()
 6     download_button = WebDriverWait(driver, 30).until(lambda x: x.find_element(By.CLASS_NAME, "CI-MDI-UNIT-DOWNLOAD"))
 7     download_button.click()
 8     csv_button = WebDriverWait(driver, 100).until(lambda x: x.find_element(By.XPATH, '/html/body/div[2]/section[2]/section/section/div/div/form/div[2]/div[2]/div[2]/div/div[2]/a'))
 9     csv_button.click()
10     
11     # 다운로드될 때까지 기다리기 (= 폴더 내 파일 개수가 일치하지 않을 때까지 기다리기)
12     while True:
13         if len(before_file_list) != len(os.listdir(download_folder_path)):
14             new_file = (set(os.listdir(download_folder_path)) - before_file_list).pop()
15             if '.csv' in new_file:
16                 break
17             
18     os.rename(download_folder_path + "/" + new_file, file_path + "/" + date + ".csv")
19     before_file_list = set(os.listdir(download_folder_path))
  • 라인 3 - 4: 날짜를 입력하는 엘리먼트를 클릭한 뒤, 자바스크립트 포맷으로 날짜를 입력합니다. 라인 4는 input 태그의 값(value)을 바꿀 때 사용하는 문법입니다. 참고로 send_keys()라는 메서드도 있지만, 이 메서드는 입력 칸이 처음에 공백일 때만 사용할 수 있습니다. 이 홈페이지는 입력 창에 내용을 다 지우면 경고 메시지가 뜨게 되어 있습니다.
  • 라인 5: 날짜를 입력했으니 조회 버튼을 클릭합니다.
  • 라인 6 - 7: 클래스 이름이 CI-MDI-UNIT-DOWNLOAD인 엘리먼트가 나올 때까지 최대 30초 기다렸다가, 나오면 해당 엘리먼트를 download_button에 저장한 뒤 클릭합니다. 이 엘리먼트도 크롬의 검사 기능을 이용하여 찾았습니다 (조만간 크롤링과 크롬 검사 기능에 대한 포스팅을 정리해야겠습니다).
  • 라인 8 - 9: 이번에는 CSV 버튼을 나타내는 태그를 XPATH의 절대경로를 이용하여 csv_button에 저장했습니다. 참고로 XPATH의 절대경로는 다음과 같이 찾았습니다.

(1) csv 버튼 우클릭 > 검사

(2) 블록 지정된 태그 우클릭

(3) Copy > Copy full Xpath 클릭

 

  • 라인 12 - 16: 데이터가 정상적으로 다운로드될 때까지 기다립니다. 즉, 기존 다운로드 폴더에 있던 파일 개수와 지금 새로 측정한 파일 개수가 같지 않고, 새로운 파일의 확장자가 csv라면 (다운로드가 완료되지 않으면 확장자는 tmp입니다) while문에서 빠져나오는 방식으로 기다립니다. 
  • 라인 18: 다운로드 폴더에 있는 새로운 파일의 이름을 os.rename 함수를 이용하여 date로 수정합니다. 여기서 경로까지 수정합니다. 
  • 라인 19: 현재 다운로드 폴더에 있는 파일 목록으로 before_file_list를 수정합니다.

이 코드를 모두 돌리고 나면 아래와 같이 주가 데이터가 다운로드됨을 알 수 있습니다.

 

 

전체 코드는 아래에서 다운로드받을 수 있습니다.

전종목주가데이터다운로드.ipynb
0.00MB

 


데이터 분석 서비스가 필요한 분은 아래 링크로! 

https://kmong.com/gig/374194 

 

데이터사이언스 박사의 데이터 분석 서비스 드립니다. | 150000원부터 시작 가능한 총 평점 5점의 I

78개 총 작업 개수 완료한 총 평점 5점인 데이터사이언스박사의 IT·프로그래밍, 데이터 분석·시각화 서비스를 68개의 리뷰와 함께 확인해 보세요. IT·프로그래밍, 데이터 분석·시각화 제공 등 150

kmong.com

 

Comments