EXCELSIOR

5. Pandas를 이용한 Naver금융에서 주식데이터 가져오기 본문

Python/주식 분석

5. Pandas를 이용한 Naver금융에서 주식데이터 가져오기

Excelsior-JH 2017. 11. 20. 01:35

Pandas를 이용한 Naver금융에서 주식데이터 가져오기


이전에 포스팅한 3. 주식 데이터를 PostgreSQL에 저장하기에서는 주식데이터를 수집하기 위해서 증권API인 크레온Plus를 이용했다. 하지만, 이 증권API가 여간 귀찮은게 아니다. 증권API를 사용하려면 증권계좌를 만들어야 하고, Windows환경에서만 실행이되기 때문에 Mac OS에서는 사용이 불가했다. 또한, Windows 32bit환경에서 관리자 권한으로 증권API를 실행 해준 뒤에 파이썬으로 주식데이터를 수집할 수 있어 엄청 불편했다. 마지막으로 PostgreSQL이라는 DB에 저장해야 하기 때문에 별도의 DB를 설치해줘야 했다.
따라서, 이번 포스팅에서는 증권API와 DB를 이용하지 않고 Python 데이터 분석 모듈인 Pandas를 이용해 Naver금융에서 주식데이터를 가져와 보도록 하자.

1. pandas 모듈 설치하기

pandas Python의 대표적인 데이터 분석 툴로써, 데이터 분석과 관련된 다양한 기능을 제공한다. (R과 비슷하다고 보면 될듯) pandas를 사용하기 위해서는 다음의 명령어로 설치를 해야한다.

  • pandas 설치: pip install pandas

2. 한국거래소(krx)에서 종목코드 가져오기

네이버금융에서 원하는 종목의 주식데이터를 가져오기 위해 먼저 코스피(KOSPI)과 코스닥(KOSDAQ)의 종목코드가 필요하다. 한국거래소(krx)에서는 주식시장에 상장된 기업들에 대해 종목코드를 제공한다. pandas모듈의 pandas.read_html()을 이용해 종목코드를 가져올 수 있다. pandas.read_html()은 HTML에서 <table></table>태그를 찾아 자동으로 DataFrame형식으로 만들어준다. 아래의 소스코드를 통해 주식의 종목코드를 가져올 수 있다.

import pandas as pd

code_df = pd.read_html('http://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13', header=0)[0]

# 종목코드가 6자리이기 때문에 6자리를 맞춰주기 위해 설정해줌
code_df.종목코드 = code_df.종목코드.map('{:06d}'.format)

# 우리가 필요한 것은 회사명과 종목코드이기 때문에 필요없는 column들은 제외해준다.
code_df = code_df[['회사명', '종목코드']]

# 한글로된 컬럼명을 영어로 바꿔준다.
code_df = code_df.rename(columns={'회사명': 'name', '종목코드': 'code'})
code_df.head()

head()함수를 통해 상위 5개의 코드를 확인할 수 있다.

N0.namecode
0BYC001460
1

CJ CGV

079160
2CJ씨푸드011150
3DSR제강069730
4KB금융105560

3. 네이버금융(Naver금융)에서 종목 별 일자 데이터 가져오기

이제 네이버금융에서 원하는 종목의 일자 데이터를 가져와 보도록 하자. 여기서는 신라젠(215600) 의 일자 데이터를 가져온다. 아래의 소스코드는 특정 종목뿐만 아니라 사용자가 원하는 종목의 일자데이터를 가져올 수 있도록 get_url이라는 함수를 만들어 줬다.
아래의 그림처럼 신라젠의 일자 데이터 url (http://finance.naver.com/item/sise_day.nhn?code=215600)에서 페이지로 구분되어 있는것을 확인할 수 있다. 각 종목마다 페이지 수가 다르기 때문에 BeautifulSoup이나 Scrapy를 이용하여 페이지 수를 크롤링하는 방법이 있지만 20페이지 정도만 가져와도 충분하다고 판단하여 별도의 크롤링 없이 20페이지만 가져오도록 지정해줬다. 크롤링을 적용하고 싶으면 Python/Web Crawling을 참고하면 된다.



# 종목 이름을 입력하면 종목에 해당하는 코드를 불러와
# 네이버 금융(http://finance.naver.com)에 넣어줌
def get_url(item_name, code_df):
    code = code_df.query("name=='{}'".format(item_name))['code'].to_string(index=False)
    url = 'http://finance.naver.com/item/sise_day.nhn?code={code}'.format(code=code)
    
    print("요청 URL = {}".format(url))
    return url
    

# 신라젠의 일자데이터 url 가져오기
item_name='신라젠'
url = get_url(item_name, code_df)

# 일자 데이터를 담을 df라는 DataFrame 정의
df = pd.DataFrame()

# 1페이지에서 20페이지의 데이터만 가져오기
for page in range(1, 21):
    pg_url = '{url}&page={page}'.format(url=url, page=page)
    df = df.append(pd.read_html(pg_url, header=0)[0], ignore_index=True)

# df.dropna()를 이용해 결측값 있는 행 제거
df = df.dropna()

# 상위 5개 데이터 확인하기
df.head()

df.head()를 이용해 상위 5개의 데이터를 아래의 출력결과와 같이 확인할 수 있다.

No.날짜종가전일비시가고가저가거래량
02017.11.179800009920099800966001973229
12017.11.1698000110099500102000913004726419
22017.11.1596900750091200100800901008936953
32017.11.148940088008140089600806006650916
42017.11.138060050007340080700731003941332

아래의 소스코드는 추후에 데이터 분석에서 편하게 하기위해 추가적으로 처리해 준 코드이다.

# 한글로 된 컬럼명을 영어로 바꿔줌
df = df.rename(columns= {'날짜': 'date', '종가': 'close', '전일비': 'diff', 
                         '시가': 'open', '고가': 'high', '저가': 'low', '거래량': 'volume'})

# 데이터의 타입을 int형으로 바꿔줌
df[['close', 'diff', 'open', 'high', 'low', 'volume']] \
    = df[['close', 'diff', 'open', 'high', 'low', 'volume']].astype(int)

# 컬럼명 'date'의 타입을 date로 바꿔줌
df['date'] = pd.to_datetime(df['date'])

# 일자(date)를 기준으로 오름차순 정렬
df = df.sort_values(by=['date'], ascending=True)

# 상위 5개 데이터 확인
df.head()
No.dateclosediffopenhighlowvolume
1992017-01-204580010045500460504515020825
1982017-01-23497503950461005070045450159477
1972017-01-2448200155049400502004750078155
1962017-01-254880060048200495004780040730
1952017-01-264810070049100491004760018716

4. Plotly를 이용해 Time Series 그래프 그리기

마지막으로 plotly를 이용하여 Time Series를 그려보도록 한다. plotly에 대한 설명은 이전 포스팅인 4. Plotly를 이용한 캔들차트-Candlestick chart 그리기를 참고하면 된다.
아래의 소스코드를 통해 Time Series 그래프를 그릴 수 있다.

# 필요한 모듈 import 하기
import plotly.offline as offline 
import plotly.graph_objs as go 

# jupyter notebook 에서 출력 
offline.init_notebook_mode(connected=True)

trace = go.Scatter(
                x=df.date,
                y=df.close,
                name=item_name)

data = [trace]

# data = [celltrion]
layout = dict(
            title='{}의 종가(close) Time Series'.format(item_name),
            xaxis=dict(
                rangeselector=dict(
                    buttons=list([
                        dict(count=1,
                             label='1m',
                             step='month',
                             stepmode='backward'),
                        dict(count=3,
                             label='3m',
                             step='month',
                             stepmode='backward'),
                        dict(count=6,
                             label='6m',
                             step='month',
                             stepmode='backward'),
                        dict(step='all')
                    ])
                ),
                rangeslider=dict(),
                type='date'
            )
        )

fig = go.Figure(data=data, layout=layout)
offline.iplot(fig)

Comments