티스토리 뷰

오늘은 이전에 만들었던 "종목별, 일자별 크롤링 프로그램" 을 자동화 해보고자 한다.

네이버에서 종목별, 일자별 크롤링 프로그램 보러가기 ☜

 

(주식 자동 매매) 네이버에서 KOSPI 종목 일자별 가격 정보 크롤링 하기 (feat. beautifulsoup, dataframe)

naver에서 종목별, 일자별 가격 data를 받아오는 코드를 작성해 보겠다 사실 키움증권API나 ystockquote등을 사용해서 주식시세 데이터를 불러오는 방법도 시도했었으나, 키움증권API는 데이터 제한이

justdoitman.tistory.com


일단 구현해야할 부분은 아래와 같다.

  1. 지금 가지고 있는 데이터의 가장 최근일과 업데이트 일자와의 차이를 구한다
  2. 그 차이에 해당하는 일자에 대한 가격데이터를 크롤링 한다
  3. 원본 데이터에 크롤링 데이터를 붙인다 (행 붙임, concat)
  4. 1~3번까지를 일정 시간에 컴퓨터가 자동적으로 수행하도록 한다.

이전에 만들었던 코드로 작업을 했다는 가정하에
그 결과물로 "KOSPI_closePrice.csv" 파일을 가지고 있어야 한다.

우선 csv파일을 불러오고
네이버에서 오늘자 가격정보도 불러와보자

 

import requests
from datetime import datetime, timedelta
import pandas as pd
from bs4 import BeautifulSoup as bs

#파일 로드 / 날짜정렬/ 날짜data 변환
dfClose = pd.read_csv("kospi_closePrice") 
dfClose = dfClose.sort_values(by = 'date') 
dfClose['date'] = pd.to_datetime(dfClose['date'])

#결측일수 구하기
latestDay = dfOpen["date"][0]
print("lastdate :" + str(latestDay))
today = datetime.now()
deltaDay = (today-latestDay).days


이제 결측일수 만큼만 가격정보를 불러와 datafam으로 저장하는 함수를 만들어보자

def updatePriceData(code, deltaDay): 
    url = 'https://finance.naver.com/item/sise_day.naver?code=' + code
    headers = {'User-agent': 'Mozilla/5.0'}
    df = pd.DataFrame() #빈 dataframe 만들기 
    
    for p in range (1, math.ceil(deltaDay/10)+1):
        pageUrl = '{}&page={}'.format(url, p) #이렇게 하는 이유는 p가 int인데, pageUrl은 str이라서
        pageReq = requests.get(url=pageUrl, headers= headers)
        dfPage = pd.read_html(pageReq.text)[0] #페이지의 가격 정보를 dataframe형식으로 전환
        df = pd.concat([df, dfPage]) #하나의 dataframe에 행으로 이어붙이기
        
    #dataframe은 모두 string이기 때문에 자료형 변경
    df = df.rename(columns={'날짜':'date','종가':'close','전일비':'diff'
                ,'시가':'open','고가':'high','저가':'low','거래량':'volume'}) #영문으로 컬럼명 변경
    df['date'] = pd.to_datetime(df['date']) 
    df = df.dropna()
    df[['close', 'diff', 'open', 'high', 'low', 'volume']] = \
                            df[['close','diff', 'open', 'high', 'low', 'volume']].astype(int) # int형으로 변경
    df = df[['date', 'open', 'high', 'low', 'close', 'diff', 'volume']] # 컬럼 순서 정렬

    return df

 

코스피 목록 불러오는 함수

같은 폴더에 "kospi_list"라는 파일이 있어야 한다.

def getCodeList():
    df = pd.read_csv('kospi_list') #코스피 목록 불러오기
    lists = df['종목코드'].values.tolist() #코스피 종목코드 리스트
    return lists

 

마지막으로 업데이트후 파일로 다시 저장한다.

#빈 dataframe 만들기 with 'date' column 
dfUdpatedClose = pd.DataFrame(columns={'date'}) 

# 각 종목별로 종가를 뽑아서 하나의 dataframe에 합치기 (column기준) 
for code in codeList:
    rawDf = updatePriceData(code, deltaDay) #종목에 대한 가격 정보 가져오기

    #업데이트데이터 추가
    dfc = pd.DataFrame({'date' : rawDf['date'],"{}".format(code) : rawDf['close']})
    dfUdpatedClose = pd.merge(dfUdpatedClose, dfc, how = 'outer', on='date')

#기존 파일에 업데이트 데이터 추가 + 중복제거 + 저장
dfClose = pd.concat([dfClose, dfUdpatedClose])
dfClose = dfClose.drop_duplicates(['date'])
dfClose.to_csv('KOSPI_closePrice_updated_{}'.format(datetime.now().strftime("%Y%m%d"))) 

print("done")


이제 업데이트 할 수 있는 코드가 완성 되었다.

그렇다면 이것을 자동화 해보자!


본인은 윈도우10를 사용하고 있어서,
윈도우의 작업 스케쥴러를 통해 자동화를 해보려고 한다.

 

작업스케쥴러를 통한 자동화 순서는 다음과 같다

  1. Batch파일 (*.bat)을 만든다
  2. 작업스케쥴러에 batch파일을 등록한다.

배치파일(bat파일) 만들기

배치 파일은 확장자가 *.bat으로 끝나는 파일이고, 그냥 만들면 된다 ㅎㅎㅎ

그냥 아무 파일이나 만들고
확장자명을 bat으로 바꾸면
쨔잔!

그리고 Bat파일의 내용을 아래와 같이 입력한다.

Visual studio code를 사용해 위와 같이 입력하였다

 


작업스케쥴러에 batch파일을 등록하기

 

작업스케쥴러는 시작화면에서 검색하거나

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools

경로에 들어가서 확인 할 수 있다

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools

작업스케쥴러를 실행하면 아래와 같은 화면이 뜬다

 

작업을 만들면 트리거 우선 작업 이름을 지어주고, 우선 권한을 주어야 한다

그리고 "트리거" 탭으로 가서, 언제 작업을 실행할지 정한다

 

다음은 "동작" 탭으로 가서, 어떤 파일을 실행할 것인지 지정해 준다

 

마지막으로 작업스케쥴러 라이브러리를 클릭하면, 만들어진 작업을 볼 수 있다.


하지만 만약 anaconda 환경에서 이렇게 실행하면 하면... 

실행이 안되는데!!!

 

그 이유는, 파이썬을 실행할 때 anaconda의 환경변수를 가져오지 못하기 때문이다

 

실제 VSCode에서 update.py를 실행하기 전에 anaconda 환경을 먼저 설정 해두는 것을 확인 할 수 있다.

그래서 bat파일의 내용을 아래와 같이 수정해서

 

파이썬 파일을 실행하기 전에 아나콘다 완경으로 먼저 만들어 주어야 한다.

참고로 나는 아나콘다를 C:\Anaconda3에 설치해서, 아래 내용을 적을 때는 경로를 잘 확인 해야한다!

 

끝.

 


전체 코드

import requests
from datetime import datetime, timedelta
import pandas as pd
from bs4 import BeautifulSoup as bs
import math

def getCodeList():
    df = pd.read_csv('db\kospi_list') #코스피 목록 불러오기
    lists = df['종목코드'].values.tolist() #코스피 종목코드 리스트
    return lists

def updatePriceData(code, deltaDay): 
    url = 'https://finance.naver.com/item/sise_day.naver?code=' + code
    headers = {'User-agent': 'Mozilla/5.0'}
    df = pd.DataFrame() #빈 dataframe 만들기 
    
    for p in range (1, math.ceil(deltaDay/10)+1):
        pageUrl = '{}&page={}'.format(url, p) #이렇게 하는 이유는 p가 int인데, pageUrl은 str이라서
        pageReq = requests.get(url=pageUrl, headers= headers)
        dfPage = pd.read_html(pageReq.text)[0] #페이지의 가격 정보를 dataframe형식으로 전환
        df = pd.concat([df, dfPage]) #하나의 dataframe에 행으로 이어붙이기
        
    #dataframe은 모두 string이기 때문에 자료형 변경
    df = df.rename(columns={'날짜':'date','종가':'close','전일비':'diff'
                ,'시가':'open','고가':'high','저가':'low','거래량':'volume'}) #영문으로 컬럼명 변경
    df['date'] = pd.to_datetime(df['date']) 
    df = df.dropna()
    df[['close', 'diff', 'open', 'high', 'low', 'volume']] = \
                            df[['close','diff', 'open', 'high', 'low', 'volume']].astype(int) # int형으로 변경
    df = df[['date', 'open', 'high', 'low', 'close', 'diff', 'volume']] # 컬럼 순서 정렬

    return df

codeList = getCodeList() 

#파일 로드 / 날짜정렬/ 날짜data 변환
dfClose = pd.read_csv("kospi_closePrice") 
dfClose = dfClose.sort_values(by = 'date') 
dfClose['date'] = pd.to_datetime(dfClose['date'])

#결측일수 구하기
latestDay = dfOpen["date"][0]
print("lastdate :" + str(latestDay))
today = datetime.now()
deltaDay = (today-latestDay).days

#빈 dataframe 만들기 with 'date' column 
dfUdpatedClose = pd.DataFrame(columns={'date'}) 

# 각 종목별로 종가를 뽑아서 하나의 dataframe에 합치기 (column기준) 
for code in codeList:
    rawDf = updatePriceData(code, deltaDay) #종목에 대한 가격 정보 가져오기

    #업데이트데이터 추가
    dfc = pd.DataFrame({'date' : rawDf['date'],"{}".format(code) : rawDf['close']})
    dfUdpatedClose = pd.merge(dfUdpatedClose, dfc, how = 'outer', on='date')

#기존 파일에 업데이트 데이터 추가 + 중복제거 + 저장
dfClose = pd.concat([dfClose, dfUdpatedClose])
dfClose = dfClose.drop_duplicates(['date'])
dfClose.to_csv('KOSPI_closePrice_updated_{}'.format(datetime.now().strftime("%Y%m%d"))) 

print("done")



<참고사이트>
https://ybworld.tistory.com/51

 

[Python/파이썬] Pandas 기초 정리 : Dataframe 행, 열 삭제하기(drop 함수)

※ 이 글을 쓰는 사람은 SW 비전공자입니다. ※ 개인 공부를 위해 정리하는 글이며, 작성한 코드들은 효율성, 깔끔함(?) 등과는 거리가 멀 수 있습니다. 1편 : 2021.03.31 - [코딩/Python] - [Python/파이썬]

ybworld.tistory.com

https://jangjy.tistory.com/362

 

Anaconda 가상환경 구동 및 프로그램실행을 batch로 만들자

anaconda 가상환경을 구축하고 사용 할 경우 특정 코드를 실행시키기 위해서는 몇번의 단계가 있다. anaconda prompt 실행 - conda env activete - path 이동 - 코드 실행... 자주 사용 할 경우에는 매번 이렇게..

jangjy.tistory.com

 

728x90
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함