본문 바로가기
방구석코딩/주식 크롤링 분석

[파이썬] 주식 데이터 크롤링(7) - csv로 저장

by 석세상 2024. 7. 16.
반응형

앞에서 파이썬을 이용하여 주식 데이터 크롤링을 위해 웹 페이지에 있는 정보를 파이썬으로 가져오는 부분까지 진행했다.

하지만 반복문을 수행하면서 동일한 데이터프레임명으로 저장하는 과정에서 반복문의 가장 마지막 정보만 파이썬으로 가져오게 되었는데 이 부분을 csv 파일로 저장하면서 해결해보기로 한다.

 

앞의 내용을 참고하여 보기 위해 기존에 진행했던 내용을 확인하고 저장하는 과정과 문제점에 대해서 해결하자.

 

[파이썬] 주식 데이터 크롤링(6) - 웹 페이지 데이터 가져오기 (for문)

파이썬을 주식 데이터 크롤링을 위해서는 앞부분까지는 웹 브라우저에서 실행 및 제어하는 부분이었다면, 이제는 이렇게 원하는 페이지의 정보를 파이썬으로 데이터를 가져오는 영역이다. 데

gusugi.tistory.com

 

 

 

기존 문제점 해결 아이디어

기존에 웹 페이지의 주식 정보를 가져오는데 있어 반복문에 동일한 데이터프레임에 덮어쓰기가 되면서 가장 마지막 정보만 보이게 되었다.

 

이 문제를 해결하기 위해서는 반복문을 실행하는 과정에서 csv 파일로 저장하면서 새 반복문에 대한 데이터를 행(아래로)으로 붙여 넣으면서 반복문이 실행되면 해결될 것 같다.

 

아래 코드를 보면서 확인해보도록 하자.

 

코드 적용

기존의 코드를 보면 아래와 같이 작성되어 있는데 이때 for문 안에서 csv 파일을 저장하고, 저장하는 파일에 다음 반복문의 실행 결과를 csv에 누적하여 저장되도록 작성하면 될 것으로 생각된다.

#########################################################################
# 04. 데이터 가져오기
#########################################################################

p_url = 'https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page='

#############################################
# (1) 1페이지부터 마지막 페이지까지 필요 테이블 불러오기
for idx in range(1, 46) :            # 마지막 페이지까지 반복, mk_lspg_num 해당 시장 종목 페이지 마지막 번호
    browser.get(p_url + str(idx))                # http 주소는 문자이기 때문에 str을 이용하여 숫자를 문자로 변경해줘야함
    
    # df = pd.read_html(browser.page_source)
    df = pd.read_html(browser.page_source)[1]     # 아래에서 각 테이블 정보를 확인해서 필요한 정보가 들어있는 [1] 테이블의 정보를 가져옴


    
    #############################################
    # (2) 불필요한 데이터 정제
    # 전체가 NaN인 데이터를 보면 네이버증권에서 확인해보면 선이 그려진 부분으로 데이터가 없는 부분임, 소스코드 확인

    df.dropna(axis = 'index', how = 'all', inplace = True)
    # dropna : 값이 없는 항목 삭제, index : row 기준으로 삭제 옵션
    # how = all 줄 전체가 결측일 때 삭제 / any를 넣으면 하나라도 결측이면 삭제
    # inplace = True : 결측인 값을 제거한 부분을 실제 데이터 프레임에 적용하는 옵션, 사용하지 않는 경우는 데이터 프레임에 직접 반영되지는 않음

    # 컬럼에서 결측만 있는 정보는 삭제
    # 네이버 증권에서는 최대 6개까지 선택이 가능하기 때문에 그 이하로 선택한 경우 나머지 칸은 값이 없는 컬럼으로 생성되고 토론실 컬럼이 결측으로 생성됨
    df.dropna(axis = 'columns', how = 'all', inplace = True)       # columns는 컬럼 기준으로 적용
    
    # (3) 반복문 실행 시 df의 데이터를 csv에 누적하여 저장

 

그러면 먼저 csv 파일로 파이썬의 데이터를 저장하는 방법을 알아보자.

 

csv 파일로 저장하기

csv 파일로 데이터를 저장하는 명령은 생각보다 간단하다. 기본적으로는 테이블명.to_csv(파일경로 및 저장할 파일명)으로 작성하면 된다. 다만 여기서 몇가지 옵션이 있다.

# csv 파일로 저장하기
# 테이블명.to_csv(경로 및 파일명, encoding =, index, header)

f_name = '/Users/hd/Documents/python/stock_pgm/01.raw_data/kospi.csv'
df.to_csv(f_name, encoding = 'utf-8-sig', index = False, mode = 'a' header = True)

코드를 하나씩 살펴보면 f_name으로 파일 경로 및 파일명을 입력한다. 아래 to_csv 괄호안에 입력해도 되지만 향후 수정이 발생할 경우 쉽게 변경하기 위해 f_name으로 경로 및 파일명을 입력해주고 아래 to_csv에 적용시켜 준다.

 

encoding 부분은 한글이 깨지는 걸 방지하기 위해 'utf-8-sig'값을 입력해준다.  index는 아래 df를 보면 맨 왼쪽편에 1,2,3,4, ... 숫자가 보이는데 이 부분이 index이다. 우리가 가져오려는 정보에 필요없는 부분이므로 제외해주기 위해 False를 입력한다.

 

다음으로 mode가 보이는데 이 부분이 중요한 부분이다. mode에서 'a'를 주면 동일한 파일 이름으로 데이터를 저장하면 파일에 새로운 정보가 누적되어 저장된다. 만약 덮어쓰기를 원한다면 'w'를 입력해주면 된다.

 

마지막으로 header 부분은 컬럼명을 가져올지의 여부를 정하는 건데 False를 입력하면 컬럼명을 제외하고 True를 입력하면 컬럼명까지 저장한다.

 

csv 파일 저장 시 설정사항

앞의 csv 파일을 그대로 for문에 적용한다면 header가 True로 되어있어 매 페이지마다 컬럼명까지 가져와서 저장하게 되는 문제점이 발생한다. 현재 코스피 종목 페이지는 45페이지까지 있으므로 2번째 반복부터는 header가 데이터 값으로 44번 저장되는 것이다.

728x90

이 부분을 해결하기 위해서는 다음과 같은 방법을 써야 하는데 파일의 존재 여부 등을 확인하기 위한 os 패키지가 필요하다.

import os

 

다음과 같이 os 패키지를 불러온 뒤 if문을 이용하여 해당 경로에 파일이 존재하는지 체크하여 아래와 같이 작성한다. os.path.exists는 해당 경로에 파일이 있는지 체크한다. 

 

만약 파일이 있다면 header = 'False'로 설정하여 헤더를 제외하고 누적하여 저장하게 하고 해당 경로에 파일이 없는 경우에만 header = 'True'를 적용하여 컬럼명까지 저장한다.

f_name = '/Users/hd/Documents/python/stock_pgm/01.raw_data/kospi.csv'

# 파일이 있다면 헤더 제외
if os.path.exists(f_name) :
    df.to_csv(f_name, encoding = 'utf-8-sig', mode = 'a', index = False, header = False)

# 파일이 없는 경우 헤더 포함, 첫 파일 생성 시
else :
    df.to_csv(f_name, encoding = 'utf-8-sig', mode = 'a', index = False, header = True)

 

 

최종코드

그러면 웹 페이지에서 정보를 가져오는 부분에서 csv 파일로 저장하는 것까지 for문에 다음과 같이 정리할 수 있다. 이렇게 저장하면 코스피의 모든 종목을 하나의 csv 파일에 저장할 수 있다. 

#########################################################################
# 04. 데이터 가져오기 및 csv 파일 저장
#########################################################################
import os

p_url = 'https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page='

#############################################
# (1) 1페이지부터 마지막 페이지까지 필요 테이블 불러오기
for idx in range(1, 46) :            # 마지막 페이지까지 반복, mk_lspg_num 해당 시장 종목 페이지 마지막 번호
    browser.get(p_url + str(idx))                # http 주소는 문자이기 때문에 str을 이용하여 숫자를 문자로 변경해줘야함
    df = pd.read_html(browser.page_source)[1]     # 아래에서 각 테이블 정보를 확인해서 필요한 정보가 들어있는 [1] 테이블의 정보를 가져옴
    
    #############################################
    # (2) 불필요한 데이터 정제
    # 전체가 NaN인 데이터를 보면 네이버증권에서 확인해보면 선이 그려진 부분으로 데이터가 없는 부분임, 소스코드 확인

    df.dropna(axis = 'index', how = 'all', inplace = True)
    df.dropna(axis = 'columns', how = 'all', inplace = True)       # columns는 컬럼 기준으로 적용
    
    #############################################
    # (3) 반복문 실행 시 df의 데이터를 csv에 누적하여 저장
    f_name = '/Users/hd/Documents/python/stock_pgm/01.raw_data/kospi.csv'

	# 파일이 있다면 헤더 제외
	if os.path.exists(f_name) :
    	df.to_csv(f_name, encoding = 'utf-8-sig', mode = 'a', index = False, header = False)

	# 파일이 없는 경우 헤더 포함, 첫 파일 생성 시
	else :
    	df.to_csv(f_name, encoding = 'utf-8-sig', mode = 'a', index = False, header = True)

다만 여기서는 하나의 파일에 계속 누적하여 저장하기 때문에 만약 동일한 날짜에 한번 더 코드를 실행한다면 똑같은 데이터가 누적된다는 문제점이 있다. 따라서 매번 확인하고 작업을 하던가 동일한 데이터가 발생 시 처리할 수 있는 코드를 생성하는 것도 방법이다.

 

또한 6개외의 나머지 체크항목과 코스닥 종목의 정보도 가져오지 못했다. 이 부분은 다음 부분부터 해결해보도록 하자.

728x90
반응형

댓글