2. Data를 파싱하여 깔끔한 출력으로 만들기
앞에서 찾은 URL을 확인하면 4가지 검색조건이 존재함을 알 수 있다.
종목코드, 검색시작 날짜, 검색종료날짜, 일봉-주봉-월봉 이다. 이를 참고하여 코딩을 진행한다.
https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&
endTime=20210901&timeframe=day
먼저 기본적인 틀을 잡아준다. 함수에는 4가지 검색 조건을 변수로 넣어주었다. 기본적으로 변수값을 입력하지 않으면
종목은 삼성전자(005930), 기간은 오늘로부터 300일(거래일 1년), 봉은 일봉으로 설정하도록 하였다.
from bs4 import BeautifulSoup # 파싱용 라이브러리
from urllib.request import urlopen # url을 가져오기위한 라이브러리
import ssl # 인증서 충돌 방지용
import pandas as pd # Dataframe 형태로 만들기 위한 판다스 라이브러리
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
pass
# 테스트를 위한 구간
if __name__ == '__main__':
pass
이제 ohlcv_data 함수에서 html 주소에서 데이터를 가져오도록 하자.
변수url에 파싱할 url을할당하고, urlopen을 이용해 소켓 객체용 ssl래퍼로 url을 지정하고
soup 변수에 BeautifulSoup을 이용하여 위 res를 html 파서로 utf-8 인코딩으로 파싱을 지정한다.
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
print(soup)
if __name__ == '__main__':
ohlcv_data()
파서를 [html.parser]를 이용하는 이유는 html형식 문서를 파싱하기 때문이고
인코딩을 utf-8로 따로 지정해주는 이유는 한글이 깨지는것을 방지해주기 위함이다(보통 utf-8을 사용한다.)
소켓 객체용 래퍼 지정에 대해서 심도있는 공부를 원한다면 아래 링크를 참고하면 된다.
https://docs.python.org/ko/3/library/ssl.html
그리고 RUN을 진행하면 아래와 같이 파싱이 된것을 볼 수 있다.
이제 이 데이터를 list형태에 한 데이터씩 들어가도록 split할 것인데, 각 데이터들이 쉼표( , )로 나뉘어 있지만, 각 데이터 내부의 값들도 쉼표로 나뉘어있기 때문에, 더 스플릿이 명확하게 되는 " ], "으로 스플릿을 진행해보자
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],') # [, 로 스플릿 진행
print("1번째 값" +data[0])
print("2번째 값" +data[1])
print("3번째 값" +data[2])
if __name__ == '__main__':
ohlcv_data()
이렇게 스플릿 된 각각의 값을 출력해보면 아래와 같이 출력되는 것을 알 수 있다.
이제 각 값에서 다시 쉼표 띄어쓰기 ", " 기준으로 스플릿 하여 날짜, 시가, 고가, 저가, 종가, 거래량으로 나누도록 해보자. 대표로 2번째 값인 ["20190624", 45200, 45800, 45200, 45500, 6085066, 57.14 을
쉼표 띄어쓰기", " 기준으로 스플릿 해보자
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],')
data2 = data[1].split(', ')
print("1번째 값"+data2[0])
print("2번째 값"+data2[1])
print("3번째 값"+data2[2])
print("4번째 값"+data2[3])
print("5번째 값"+data2[4])
print("6번째 값"+data2[5])
if __name__ == '__main__':
ohlcv_data()
그럼 아래와 같이 data[1]이 6개의 값을 가지는 list인 data2로 스플릿 된 것을 확인 할 수 있다.
OHLCV 데이터는 별도의 수정이 필요하지 않게 파싱이 되었는데, 날짜 값이 지저분하게 파싱되었다.
data2[0]이 날짜가 포함된 값이고 이것을 다시 "[ 를 기준으로 스플릿 해보면
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],')
data2 = data[1].split(', ')
data3 = data2[0].split('["') # data2의 리스트 1번 값인 날짜가 포함된 문자를 ["로 스플릿
print(data3)
if __name__ == '__main__':
ohlcv_data()
아래와같이 1번째 값(0번째랑 헷갈리지 않도록 한다)에 날짜가 나온다.
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],')
data2 = data[1].split(', ')
data3 = data2[0].split('["')
data4 = data3[1].split('"') # 쌍따옴표로 스플릿
print(data4)
if __name__ == '__main__':
ohlcv_data()
여기서 마지막으로 다시 쌍따옴표 " 를 기준으로 스플릿하면
0번 째 값으로 날짜를 출력할 수 있다.
즉 위 코드를 좀 정리하면 날짜는 data를 <],> 로 스플릿한 1번째 값을 <, >로 스플릿한 0번째 값을 <[">로 스플릿한 1번째 값을 <">로 스플릿한 0번째 값이 된다. 왜 이렇게 split만 쓰는가 의문이 들 수 있는데, html 게시자 (여기서는 네이버)가 html의 포맷을 바꾸게 될 경우 replace나 remove에 비해 split이 더욱 유연하게 대응이 가능하기 때문이다.
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],')
data2 = data[1].split(', ')
data3 = data2[0].split('["')
data4 = data3[1].split('"')
date = str(soup).split('],')[1].split(', ')[0].split('["')[1].split('"')[0]
print(date)
if __name__ == '__main__':
ohlcv_data()
이제 코드를 조금 더 정리해서 값을 각 변수에 할당하도록 하자
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],')
date = data[1].split(', ')[0].split('["')[1].split('"')[0] #data[1]에 대해서만
open = data[1].split(', ')[1] #data[1]에 대해서만
high = data[1].split(', ')[2] #data[1]에 대해서만
close = data[1].split(', ')[3] #data[1]에 대해서만
low = data[1].split(', ')[4] #data[1]에 대해서만
volume = data[1].split(', ')[5] #data[1]에 대해서만
print(data[1])
print(date)
print(open)
print(high)
print(close)
print(low)
print(volume)
if __name__ == '__main__':
ohlcv_data()
data[1]에 대해서 잘 작동하는것을 확인했으니, 이제 for문을 이용하여 모든 데이터에 대해서 작동하도록 바꿔보자
for i in range(1, len(data))를 사용하는데, 1번째부터인 이유는 위에서 봤듯이 0번째 값이 [날짜, 고가... ] 이기 때문이다.
len(data)는 data에 포함된 요소의 갯수이다. 즉 1번째 부터 끝까지 for 문을 진행하는 것이다.
def ohlcv_data(code='005930',starttime='default',endtime='today',timeframe='day'):
url = 'https://api.finance.naver.com/siseJson.naver?symbol=005930&requestType=1&startTime=20190624&endTime=20210901&timeframe=day'
res = urlopen(url, context=ssl.create_default_context())
soup = BeautifulSoup(res.read(), 'html.parser', from_encoding='utf-8')
data = str(soup).split('],')
for i in range(1,len(data)): # 0번값은 [날짜, 고가 .. 이기 떄문에 1번째 값부터 시작한다.
date = data[i].split(', ')[0].split('["')[1].split('"')[0]
open = data[i].split(', ')[1]
high = data[i].split(', ')[2]
close = data[i].split(', ')[3]
low = data[i].split(', ')[4]
volume = data[i].split(', ')[5]
print(date, open, high, close, low, volume)
if __name__ == '__main__':
ohlcv_data()
그러면 아래와 같이 원하는 값으로 나오는 것을 확인 할 수 있다.
Pandas Dataframe으로의 변환은 다음 글에서 진행하도록 하겠다.
'BeautifulSoup을 이용한 웹 크롤링' 카테고리의 다른 글
04. OHLCV 데이터를 파싱해 Pandas Dataframe 형태로 만들기 -3 (0) | 2021.09.03 |
---|---|
03. OHLCV 데이터를 파싱해 Pandas Dataframe 형태로 만들기 -2 (0) | 2021.09.01 |
01. Naver Finance에서 크롤링할 URL 찾기 (0) | 2021.09.01 |