Skip to main content

06. 웹 스크래핑 실습 - 종목의 캔들차트

About 2 minPythoncrashcoursepythonpygooglegoogle-colabjupyter-notebooknumpypandasipython

06. 웹 스크래핑 실습 - 종목의 캔들차트 관련


06. 웹 스크래핑 실습 - 종목의 캔들차트

금융 데이터 분석을 위한 파이썬 - WikiDocs

01. 종목의 가격 데이터 크롤링

셀트리온 종가 크롤링

import pandas as pd
import matplotlib.pyplot as plt
import requests
from datetime import datetime
from matplotlib import dates as mdates
from bs4 import BeautifulSoup as bs

아래의 주소로부터 크롤링을 해봅시다.

url = 'https://finance.naver.com/item/sise_day.nhn?code=068270&page=1'
셀트리온증가
셀트리온증가

해당 주소로 접속해보면 셀트리온의 일별 종가, 전일비, 시가, 고가, 저가, 거래량이 업데이트 되고 있는 사이트입니다. 네이버 금융 사이트에서 셀트리온을 검색 후 접속하여 얻은 주소라고 보시면 됩니다.

requests라는 패키지에 있는 get이라는 모듈(함수)에 url을 입력으로 하고, 이를 변수에 저장한 후에 변수.text를 하면 해당 URL의 HTML 코드를 받아올 수 있습니다. HTML 코드를 받아오는 방법은 아래와 같습니다.

  • response = requests.get(url)
  • response.text

HTML 코드를 받아오는 파이썬 코드를 실행하기 전에 앞서 headers라는 개념이 필요합니다.

headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'}
response = requests.get(url, headers=headers)

headers에 대한 설명open in new window

위의 링크에서 설명하고 있듯이, 유저 에이전트를 인자로 넣어서 get 함수를 사용하면 크롤링 방지 차단을 뚫고 크롤링을 할 수 있습니다. 위의 headers값은 강사의 브라우저에서 추출한 값으로 여러분들은 여러분들의 에이전트 정보를 추출해서 사용하셔도 됩니다! 이제 response.text를 출력해볼까요?

response.text
# 
# \n<html lang="ko">\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">\n<title>네이버 금융</title>\n\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/newstock.css">\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/common.css">\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/layout.css">\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/main.css">\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/newstock2.css">\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/newstock3.css">\n<link rel="stylesheet" type="text/css" href="https://ssl.pstatic.net/imgstock/static.pc/20220819210825/css/world.css">\n</head>\n<body>\n<script ... 중략 ...

BeautifulSoup4를 통해서 해당 HTML 코드를 파싱합니다.

html = bs(response.text, 'html.parser')
html_table = html.select("table")
table = pd.read_html(str(html_table))
print('파싱된 테이블의 개수 :', len(table))
#
# 파싱된 테이블의 개수 : 2

첫번째 테이블을 출력해봅시다.

table[0]
첫번째테이블
첫번째테이블
  • 불러온 결과가 저와 달라도 상관없습니다. 저는 이 실습을 2022년 8월 29일에 하였기때문에 8월 29일까지의 주가가 있는 것이고, 여러분들이 실습을 할 때는 또 그때 기준의 주가 데이터를 불러올 것입니다.

셀트리온의 일별 종가, 전일비, 시가, 고가, 저가, 거래량이 있는 테이블입니다. 다만, 중간에 결측값들이 존재합니다. 두번째 테이블을 출력해봅시다.

table[1]
두번째테이블
두번째테이블

두번째 테이블은 우리가 원하는 테이블이 아닙니다. 첫번째 테이블만을 사용한다고 가정해봅시다. 그런데 첫번째 테이블은 앞서 확인했을 때 결측값이 있었으므로 결측값을 제거하여 출력해봅시다. 단순히 결측값을 제거하는 것은 dropna()를 통해서 가능합니다.

table[0].dropna()
첫번째테이블2
첫번째테이블2

앞서 진행했던 일련의 과정들을 1페이지부터 99페이지까지 반복해봅시다.

df = pd.DataFrame()
sise_url = 'https://finance.naver.com/item/sise_day.nhn?code=068270'  
for page in range(1, 100):
    page_url = '{}&page={}'.format(sise_url, page)
    print(page_url)

    # 위에서 했던 일련의 과정들을 각 url에 대해서 (99페이지에 대해서 반복)
    response = requests.get(page_url, headers=headers)
    html = bs(response.text, 'html.parser')
    html_table = html.select("table")
    table = pd.read_html(str(html_table))

    # 현재 얻은 데이터프레임을 기존 데이터프레임에 누적.
    df = df.append(table[0].dropna())

크롤링이 끝났다면 데이터프레임을 출력해봅시다.

df
데이터프레임
데이터프레임

최근 데이터 30행만 사용하겠습니다. 네이버 금융의 데이터가 내림차순으로 되어져 있으므로 오름차순으로 변경합니다.

df = df.dropna()
df = df.iloc[0:30] 
df = df.sort_values(by='날짜')
df
셀트리온테이블
셀트리온테이블

셀트리온의 종가를 시각화해봅시다. x축 레이블의 날짜가 겹쳐서 보기어려우므로 90도 회전하여 표시했습니다. x축은 날짜 데이터로 y축은 종가 데이터로 출력합니다. co는 좌표를 청록색(cyan) 원으로, -는 각 좌표를 실선으로 연결해서 표시합니다.

plt.figure(figsize=(15, 5)) 
plt.title('Celltrion (close)')
plt.xticks(rotation=45) 
plt.plot(df['날짜'], df['종가'], 'co-')
plt.grid(color='gray', linestyle='--')
plt.show()
셀트리온증가시각화
셀트리온증가시각화

02. 캔들차트 시각화

이번 실습은 이전 실습에서 이어서 진행한다고 가정합니다.

캔들 차트에 대한 기본적인 지식open in new window

캔들 차트를 그리는 패키지는 구버전과 신버전이 있습니다.

패키지명이 비슷한데, 패키지명 중간에 하이픈(-)이나 언더스코어(_)가 있으면 예전 패키지이고, 중간에 아무 문자도 없는 것이 새로운 패키지입니다. 구버전, 새로운 신버전 두 가지 모두를 소개하겠습니다. 가급적이면 신버전 사용을 권합니다.

# 구버전 설치
!pip install --upgrade mpl_finance  

# 신버전 설치
!pip install --upgrade mplfinance

구버전 캔들차트

from mpl_finance import candlestick_ohlc

df = df.sort_values(by='날짜')

for idx in range(0, len(df)):
    # 날짜열을 datetime 형으로 변환.
    dt = datetime.strptime(df['날짜'].values[idx], '%Y.%m.%d').date() 
    # datetime 형을 float 형으로 변환
    df['날짜'].values[idx] = mdates.date2num(dt)

# candlestick_ohlc()에서 요구하는 형식으로 변경
ohlc = df[['날짜','시가','고가','저가','종가']]

plt.figure(figsize=(9, 6))
ax = plt.subplot(1, 1, 1)    
plt.title('Celltrion (mpl_finance candle stick)')

# candlestick_ohlc 함수를 이용하여 캔들차트를 그린다.
candlestick_ohlc(ax, ohlc.values, width=0.7, colorup='red', colordown='blue')

# x축의 레이블이 숫자. %Y-%m-%d 형식 문자열로 변환하여 표시
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.xticks(rotation=45)
plt.grid(color='gray', linestyle='--')
plt.show()

캔들 차트를 통해 주가 일자별로의 주가 변동폭을 확인할 수 있습니다. 캔들 차트를 위해서 사용하는 candlestick_ohlc()를 호출할 때는 두번째 인자에 OHLC 데이터를 넣어주어야 합니다.


이찬희 (MarkiiimarK)
Never Stop Learning.