본문 바로가기
Python/증권 데이터 분석

파이썬을 이용한 주식(종목코드, 회사명)정보 MariaDB로 자동 저장하기 #1

by grey-hat hacker 2021. 2. 17.
728x90

1. C:\myPackage\Investar 디렉터리를 생성!

 

2. 아래 코드를 Investar 경로에 DBUpdater.py로 저장한다!  

class DBUpdater:
    def __init__(self):
        """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성"""
        
    def __del__(self):
        """소멸자: MariaDB 연결 해제"""
        
    def read_krx_code(self):
        """KRX로부터 상장법인목록 파일을 읽어와서 데이터프레임으로 변환"""
    
    def update_comp_info(self):
        """종목코드를 company_info 테이블에 업데이트 후 딕셔너리에 저장"""
        
    def read_naver(self, code, company, pages_to_fetch):
        """네이버 금융에서 주식 시세를 읽어서 데이터프레임으로 반환"""
        
    def replace_into_db(self, df, num, code, company):
        """네이버 금융에서 읽어온 주식 시세를 DB에 REPLACE"""
        
    def update_daily_price(self, pages_to_fetch):
        """KRX 상장법인의 주식 시세를 네이버로부터 읽어서 DB에 업데이트"""
        
    def execute_daily(self):
        """실행 즉시 및 매일 오후 다섯시에 daily_price 테이블 업데이트"""
        
if __name__ == '__main__':
    dbu = DBUpdater()
    dbu.execute_daily()

3. Investar 데이터베이스에 화사명과 종목코드를 저장할 테이블(company_info), 

                                   주식 시세를 저장할(daily_price) 테이블을 생성한다. 

-> Investart 데이터베이스 생성 참고 grey-hat.tistory.com/107

> last_update 컬럼을 통해서 하루에 한 번 업데이트 하도록 설정

CREATE TABLE IF NOT EXISTS company_info(
	code VARCHAR(20),
	company VARCHAR(20),
	last_update DATE,
	PRIMARY KEY (code)
);

CREATE TABLE IF NOT EXISTS daily_price (
	code VARCHAR(20),
	DATE DATE,
	open BIGINT(20),
	high BIGINT(20),
	low BIGINT(20),
	close BIGINT(20),
	diff BIGINT(20),
	volume BIGINT(20),
	PRIMARY KEY (code, DATE)
);
	

 

- 보이는 노란색 열쇠는 복합 기본키!

- 기본키는 중복을 허용하지 않기 때문에 동일한 코드와 데이터를 자지는 데이터 행은 중복 삽입 불가이다.

 > 2020년 2월 16일 삼성전자 데이터가 존재하면 해당 테이블에는 더 이상 데이터를 중복 삽입할 수 없다. 

 

4. DBUpdater 클래스는 객체가 생성될 때 마리아디비에 접속하고. 소멸될 때 접속을 해제한다. 

  > update_comp_info() 메서드로 KRX 주식 코드를 읽어 와서 마리아의 company_info 테이블 업데이트

import pymysql

class DBUpdater:
    def __init__(self):
        """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성"""
        
        self.conn = pymysql.connect(host='localhost', user='root', password='Rlaansrl12!', db='INVESTAR', charset='utf8')
    
        with self.conn.cursor() as curs:
            sql = """company_info"""
            curs.execute(sql)
            sql = """daily_price"""
            curs.execute(sql)

        self.conn.commit()
        
        self.codes = dict()
        self.update_comp_info()
        
    def __del__(self):
        """소멸자: MariaDB 연결 해제"""
        self.conn.close()

5. .xls 파일을 read_html() 함수로 읽고

 > 특정 칼럼만 뽑아서 원하는 순서로 재구성한다. 

 > 종목코드 형식을 {:06d} 형식의 문자열로 변경한다. 

import pandas as pd
class DBUpdater:
    def read_krx_code(self):
        """KRX로부터 상장기업 목록 파일을 읽어와서 데이터프레임으로 변환"""
        url = 'http://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13'
        krx = pd.read_html(url, header=0)[0]
        krx = krx[['종목코드', '회사명']]
        krx = krx.rename(columns={'종목코드':'code', '회사명':'company'})
        krx.code = krx.code.map('{:06d}'.format)
        return krx
    

6. SELECT max() ~구문을 이용해서 DB에서 최근 업데이트 날짜를 가져온다.

 > 날짜가 있거나 오늘보다 오래된 경우에만 업데이트 한다.

 - REPLACE INTO 구문을 이용해서 '종목코드, 회사명, 오늘날짜' 행을 DB에 저장한다. 

import pandas as pd
from datetime import datetime

class DBUpdater:
    def update_comp_info(self):
        """종목코드를 company_info 테이블에 업데이트한 후 딕셔너리에 저장"""
        sql = "SELECT * FROM company_info"
        df = pd.read_sql(sql, self.conn)
        for idx in range(len(df)):
            self.codes[df['code'].values[idx]]=df['company'].values[idx]
        with self.conn.cursor() as curs:
            sql = "SELECT max(last_update) FROM company_info"
            curs.execute(sql)
            rs = curs.fetchone()
            today = datetime.today().strftime('%Y-%m-%d') 
            
            if rs[0] == None or rs[0].strftime('%Y-%m-%d') < today:
                krx = self.read_krx_code()
                for idx in range(len(krx)):
                    code = krx.code.values[idx]
                    company = krx.company.values[idx]
                    sql = f"REPLACE INTO company_info (code, company, last_update) VALUES ('{code}','{company}',{today})"
                    curs.execute(sql)
                    
                    self.codes[code] = company
                    tmnow = datetime.now().strftime('%Y-%m-%d %H:%M')
                    print(f"[{tmnow}] {idx:04d} REPLACE INTO company_info VALUES ('{code}','{company}',{today})")
                    
                self.conn.commit()
                print('')

7. 앞서 작성한 모든 함수를 모은다

import pymysql
import pandas as pd


from datetime import datetime

class DBUpdater:
    def __init__(self):
        
        self.conn = pymysql.connect(host='localhost', user='root', password='Rlaansrl12!', db='INVESTAR', charset='utf8')
    
        with self.conn.cursor() as curs:
            sql = """
                create table if not exists company_info (
                    code varchar(20),
                    company varchar(40),
                    last_update date,
                    primary key (code)
                )
            """
            curs.execute(sql)
            sql = """
                create table if not exists daily_price (
                    code varchar(20),
                    date date,
                    open bigint(20),
                    high bigint(20),
                    low bigint(20),
                    close bigint(20),
                    diff bigint(20),
                    volume bigint(20),
                    primary key (code, date)
                )
            """
            curs.execute(sql)
        self.conn.commit()

        self.codes=dict()
        self.update_comp_info()
        
    def __del__(self):
        self.conn.close()
        
    def read_krx_code(self):
        url = 'http://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13'
        krx = pd.read_html(url, header=0)[0]
        krx = krx[['종목코드', '회사명']]
        krx = krx.rename(columns={'종목코드':'code', '회사명':'company'})
        krx.code = krx.code.map('{:06d}'.format)
        return krx
    
    def update_comp_info(self):
        sql = "SELECT * FROM company_info"
        df = pd.read_sql(sql, self.conn)
        for idx in range(len(df)):
            self.codes[df['code'].values[idx]]=df['company'].values[idx]
        with self.conn.cursor() as curs:
            sql = "SELECT max(last_update) FROM company_info"
            curs.execute(sql)
            rs = curs.fetchone()
            today = datetime.today().strftime('%Y-%m-%d') 
            
            if rs[0] == None or rs[0].strftime('%Y-%m-%d') < today:
                krx = self.read_krx_code()
                for idx in range(len(krx)):
                    code = krx.code.values[idx]
                    company = krx.company.values[idx]
                    sql = f"REPLACE INTO company_info (code, company, last_update) VALUES ('{code}','{company}','{today}')"
                    curs.execute(sql)             
                    self.codes[code] = company
                    tmnow = datetime.now().strftime('%Y-%m-%d %H:%M')
                    print(f"[{tmnow}] {idx:04d} REPLACE INTO company_info VALUES ({code},{company},{today})")
                    
                self.conn.commit()
                print('')
if __name__ == '__main__':
    dbu = DBUpdater()
    dbu.update_comp_info()

 

8. C:\Users\user>python C:\myPackage\Investar\DBUpdater.py 파이썬 프로그램을 실행한다.

 > 그럼 DB 정보가 업데이트 된 것을 확인할 수 있다. 

 

728x90
반응형

댓글