언빌리버블티

[KDT] Python 웹 스크래핑으로 네이버 금융 개별종목 데이터 수집 본문

Data Science/KDT

[KDT] Python 웹 스크래핑으로 네이버 금융 개별종목 데이터 수집

나는 정은 2022. 9. 29. 16:13

멋쟁이 사자처럼 AI스쿨 3주차

: requests & BeautifulSoup 를 활용한 네이버 금융 국내 증시사이트 Web Scraping 

 

item_name = "카카오뱅크"
save_csv(item_name)
 

이렇게 단 두 줄의 코드로 내가 원하는 기업의 일별시세 정보 데이터를 수집하는 방법에 대해 알아보자 !

함수 구조

  • save_csv(종목명) : 종목 코드 할당, 데이터프레임 리스트 concat 및 csv 파일로 변환
    • get_item_list(종목 코드, 종목명) : 전체 페이지 데이터 수집 및 데이터 프레임 리스트 반환
      • get_day_list(종목코드, 페이지 번호) : url 생성 및 개별 페이지 데이터 반환

라이브러리 로드

import pandas as pd
import requests
import FinanceDataReader as fdr
import time 
 
  • pandas : 데이터 처리 및 분석 라이브러리
    • 행 * 열로 이루어진 DataFrame을 다룬다.
  • requests : 서버에 http 요청을 보내는 모듈로 인터넷 상의 html 문서를 요청하여 받아온다.
  • FinanceDataReader : 한국&미국 주식가격 , 지수, 환율, 암호화폐 가격, 종목 리스팅 등 금융 데이터 수집 라이브러리
  • time : API 불러올 때 time sleep 을 걸어 어느 정도 텀을 주고 출력하는 것이 예의

 

수집할 url 할당하기

df_krx = fdr.StockListing("KRX")

item_name = "카카오뱅크" 
item_code = df_krx.loc[df_krx["Name"] == item_name, "Symbol"].values[0]
page = 1

url = "https://finance.naver.com/item/sise_day.naver?code={item_code}&page={page_no}"
 
  • fdr의 StockListing 메서드를 통해 한국 거ㅓ래소 상장 회사 정보를 불러온다.
    • FinanceDataReader 로 불러온 내가 원하는 종목의 item_code를 받아온 뒤 쿼리 스트링 url에 할당한다.

ex ) 삼성전자(code=005930) 일별 시세 페이지의 10번째 페이지에 대한 HTML요청

 

데이터 수집하기

requests를 통한 HTTP 요청

response = requests.get(url, headers = {"user-agent":"Mozilla/5.0"})
response 
 
  • requests .get( url , header = '' ) : headers 옵션의 user-agent 를 Mozilla/5.0 로 지정하여 로봇이 아님을 알려주고 html 문서를 요청한다.

 

pandas로 데이터를 DataFrame 형식으로 받아오기

table = pd.read_html(response.text)
 
  • encoding : cp949 (한글 인코딩). 디폴트 값은 utf-8 이며, 네이버의 일별 시세는 cp949 인코딩으로 불러올 수 있다.
  • pd.read_html() : 받아온 html 문서에서 table tag를 읽어 반환한다.

 

temp = table[0].dropna().reset_index(drop='index')
temp
 
  • dropna() : table[0] 의 NaN값을 제거한 뒤 데이터프레임 변수 생성
  • reset_index(drop='index') : 데이터 프레임 인덱스를 초기화하고 기존에 있던 인덱스 변수는 남기지 않고 제거한다.

페이지 별 데이터 수집하기

초기값 설정하기

page_no = 1
item_list = []
prev_day = None 
 
  • page_no : 페이지 1부터 맨 마지막 n까지 탐색하기 위해 할당
  • item_list : 맨 끝까지 탐색해서 불러온 DataFrame들을 모두 저장
  • prev_day : 날짜를 비교하여 break를 걸어주기 위해 할당
    • 각 페이지의 맨 마지막 데이터의 저장 날짜와 같아지면 while문을 탈출한다.
      • last_day 변수에 저장된 값인 "맨 처음 (오래된) 불러온 데이터 날짜"가 될 때까지 반복한다.

반복문(While)을 사용하여 페이지의 끝까지 탐색하여 데이터 수집하기.

While True:

df_item = get_day_list(item_code, page_no)
last_day = df_item.iloc[-1]["날짜"]
 
  • get_day_list(item_code, page_no): 입력한 종목 번호+페이지 넘버에 따른 url로 만든 데이터 프레임을 반환하는 함수
  • last_day : 데이터프레임 df_item에서 저장된 날짜가 가장 오래된 데이터 저장
      • while 탈출 조건을 지정하기 위한 변수
    • iloc : 인덱스 번호를 기준으로 데이터 행에 접근

조건문 (while문 break) 지정

if last_day == prev_day:
   print(f'{page_no-1} 페이지가 마지막 페이지입니다.')
   break
 
  • 일별 시세이기 때문에 현재 날짜와 페이지 맨 마지막에 저장된 날짜를 비교한다.
    • 맨 마지막 (날짜) 데이터를 불러오고 break 한 뒤 다음 페이지로 넘어간다.

각 페이지 별 데이터 append 및 코드 진행 사항 출력

prev_day = last_day
item_list.append(df_item) 

if not page_no % 10:
   print(page_no, prev_day, last_day)
page_no += 1

time.sleep(1)
 
  • 이전 페이지 마지막 줄 날짜 last_day를 현재 페이지의 비교 날짜로 지정한다.
    • 페이지 호출 횟수가 10씩 늘어날 때마다 진행사항(현재 불러온 데이터 저장 날짜, 이전 데이터 저장 날짜) 출력
  • item_list.append() : item_list 에 가져온 페이지 별 데이터를 추가해준다.
  • time.sleep(1) : 페이지 데이터를 불러오는 시간 간격을 1초로 둔다.
    • API 호출 시 매너 : 기간이 긴 데이터를 수집할때는 서버에 부담을 주지 않기 위해 time.sleep()값 지정
  • While 문 탈출 후 전체 페이지 데이터가 저장된 item_list 리스트 반환

 

수집한 데이터를 CSV파일로 저장하기

데이터 url 생성 및 전체 페이지 데이터를 수집하는 하나의 함수를 호출

df_krx = fdr.StockListing("KRX")

item_code = df_krx.loc[df_krx["Name"] == item_name, "Symbol"].values[0]
item_list = get_item_list(item_code, item_name)
 

반환된 item_list를 하나의 데이터프레임으로 합치기

df_day = pd.concat(item_list, ignore_index=True)
 

전체 데이터 변수명 정리 & 중복 데이터 삭제 & 인덱스 초기화

cols = ['종목코드', '종목명', '날짜', '종가', '전일비', '시가', '고가', '저가', '거래량']
df_day['종목코드'] = item_code
df_day['종목명'] = item_name
df_day = df_day[cols].drop_duplicates().reset_index(drop=True)
 
  • 종목 코드와 종목명이라는 파생 변수를 생성한 뒤 item_code와 item_name을 입력
  • df_day = df_day[cols] : DataFrame columns의 이름 순서를 바꿔준다.
  • drop_duplicates() : 데이터의 중복을 제거한다.
    • row들 끼리 data를 비교한 뒤 같은 값이 있을 경우 row 전체를 삭제한다.
  • reset_index(drop=True) : index를 초기화한 뒤 이전 index 변수는 따로 남기지 않고 drop한다.

 

데이터 프레임을 CSV 형태 파일로 저장하기

date = df_day.iloc[0]["날짜"]
file_name = f'{item_name}_{item_code}_{date}.csv'
df_day.to_csv(file_name, index = False)
print('done')
 
  • df.to_csv() : csv파일로 저장한다.
    • index 옵션을 False로 두어 DF의 기본 index가 저장되지 않도록 한다.
      파일명은 종목명_종목코드_API호출날짜.csv 로 저장한다.

데이터 읽어오기

return pd.read_csv(file_name).head() 
 
  • pd.read_csv(파일명) : 파일을 읽어와서 데이터가 잘 저장되었는지 확인한다.
    • head() : 데이터를 위에서부터 5개만 출력

 

Result

# 원하는 기업명을 item_name 으로 입력하여 일별시세정보 데이터 수집

item_name = "펄어비스"
save_csv(item_name)
10 2022.05.04 2022.05.04
20 2021.12.07 2021.12.07
30 2021.07.12 2021.07.12
40 2021.02.17 2021.02.17
50 2020.09.17 2020.09.17
60 2020.04.24 2020.04.24
70 2019.11.28 2019.11.28
80 2019.07.04 2019.07.04
90 2019.02.08 2019.02.08
100 2018.09.06 2018.09.06
110 2018.04.11 2018.04.11
120 2017.11.14 2017.11.14
124 페이지가 마지막 페이지입니다.
done
 

124개의 펄어비스 일별시세 페이지에서 총 1237개의 데이터를 수집해보았다 !

 

Comments