거래소 상장법인목록 크롤링
[FinDA] 거래소(KRX) 상장법인목록 크롤링 및 MySQL DB update
1. 상장법인목록
http://kind.krx.co.kr/corpgeneral/corpList.do?method=loadInitPage
다운로드한 파일의 확장자가 xls 이지만 열어보면 html 이다.
크롬 개발자도구를 통해 EXCEL 버튼 선택시 웹브라우저의 동작을 확인한다.
검사 - Network - Name (corpList.do) - Headers
- request url : http://kind.krx.co.kr/corpgeneral/corpList.do
- Form Data 항목에서 요청에 사용된 키와 값을 확인
import pandas as pd
import numpy as np
import requests
from bs4 import BeautifulSoup
from io import BytesIO
def stock_master():
url = 'http://kind.krx.co.kr/corpgeneral/corpList.do'
data = {
'method':'download',
'orderMode':'1', # 정렬컬럼
'orderStat':'D', # 정렬 내림차순
'searchType':'13', # 검색유형: 상장법인
'fiscalYearEnd':'all', # 결산월: 전체
'location':'all', # 지역: 전체
}
r = requests.post(url, data=data)
f = BytesIO(r.content)
dfs = pd.read_html(f, header=0, parse_dates=['상장일'])
df = dfs[0].copy()
# 숫자를 앞자리가 0인 6자리 문자열로 변환
df['종목코드'] = df['종목코드'].astype(np.str)
df['종목코드'] = df['종목코드'].str.zfill(6)
return df
df_master = stock_master()
df_master.head()
회사명 | 종목코드 | 업종 | 주요제품 | 상장일 | 결산월 | 대표자명 | 홈페이지 | 지역 | |
---|---|---|---|---|---|---|---|---|---|
0 | BYC | 001460 | 봉제의복 제조업 | 메리야스,란제리 제조,도매/건축공사/부동산 임대,분양,공급 | 1975-06-02 | 12월 | 유 중 화 | http://www.byc.co.kr | 서울특별시 |
1 | CJ씨푸드 | 011150 | 기타 식품 제조업 | 수산물(어묵,맛살)가공품 도매,원양수산업,수출입 | 1988-11-26 | 12월 | 유병철, 강신호(각자대표) | http://www.cjseafood.net | 경기도 |
2 | DRB동일 | 004840 | 회사본부, 지주회사 및 경영컨설팅 서비스업 | 고무벨트(V벨트,콘베이어벨트,평벨트),프라스틱제품 제조,판매 | 1976-05-21 | 12월 | 박진삼 | http://drbworld.com | 부산광역시 |
3 | DSR제강 | 069730 | 1차 철강 제조업 | 와이어로프,각종 경강선,철선제품,PC강선,아연도 강연선 제조 | 2003-01-28 | 12월 | 홍하종 | http://www.dsrcorp.com | 전라남도 |
4 | GS건설 | 006360 | 건물 건설업 | 토목공사,건축공사,주택공사,산업플랜트공사,리모델링공사,시설물유지관리공사/산업설비설계... | 1981-08-03 | 12월 | 허창수, 임병용(각자 대표이사) | http://www.gsconst.co.kr/ | 서울특별시 |
df = df_master.loc[:, ['회사명', '종목코드', '업종', '상장일', '결산월']]
df.head()
회사명 | 종목코드 | 업종 | 상장일 | 결산월 | |
---|---|---|---|---|---|
0 | BYC | 001460 | 봉제의복 제조업 | 1975-06-02 | 12월 |
1 | CJ씨푸드 | 011150 | 기타 식품 제조업 | 1988-11-26 | 12월 |
2 | DRB동일 | 004840 | 회사본부, 지주회사 및 경영컨설팅 서비스업 | 1976-05-21 | 12월 |
3 | DSR제강 | 069730 | 1차 철강 제조업 | 2003-01-28 | 12월 |
4 | GS건설 | 006360 | 건물 건설업 | 1981-08-03 | 12월 |
2. 거래소(KRX) 전체 종목코드 크롤링 (시가총액순위)
트래픽 분석
시장정보 - 주식 - 순위정보 - 시가총액 상하위 - CSV 선택
시가총액순 종목리스트는 다음과 같이 두 단계에 걸쳐 진행된다.
- http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx
- http://file.krx.co.kr/download.jspx : GenerateOTP.jspx를 통해 리턴받은 값을 입력으로 사용한다.
데이터 가져오기
import pandas as pd
import numpy as np
import requests
from io import BytesIO
from datetime import datetime
def stock_master_price(date=None):
if date == None:
date = datetime.today().strftime('%Y%m%d') # 오늘 날짜
# STEP 01: Generate OTP
gen_otp_url = 'http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx'
gen_otp_data = {
'name':'fileDown',
'filetype':'xls',
'url':'MKD/04/0404/04040200/mkd04040200_01',
'market_gubun':'ALL', #시장구분: ALL=전체
'indx_ind_cd':'',
'sect_tp_cd':'',
'schdate': date,
'pagePath':'/contents/MKD/04/0404/04040200/MKD04040200.jsp',
}
r = requests.post(gen_otp_url, gen_otp_data)
code = r.content # 리턴받은 값을 아래 요청의 입력으로 사용.
# STEP 02: download
down_url = 'http://file.krx.co.kr/download.jspx'
down_data = {
'code': code,
}
r = requests.post(down_url, down_data)
df = pd.read_excel(BytesIO(r.content), header=0, thousands=',')
return df
df = stock_master_price()
df.head()
종목코드 | 종목명 | 현재가 | 대비 | 등락률 | 거래량 | 거래대금 | 시가총액 | 시가총액비중(%) | 상장주식수(천주) | 외국인 보유주식수 | 외국인 지분율(%) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 005930 | 삼성전자 | 2090000 | -17000 | -0.8 | 69044 | 144463049000 | 294019814330000 | 18.35 | 140679337 | NaN | NaN |
1 | 000660 | SK하이닉스 | 49300 | -1000 | -2.0 | 1449682 | 71990011200 | 35890516594500 | 2.24 | 728002365 | NaN | NaN |
2 | 005935 | 삼성전자우 | 1615000 | -25000 | -1.5 | 17531 | 28297084000 | 33129184605000 | 2.07 | 20513427 | NaN | NaN |
3 | 005380 | 현대차 | 149000 | -1000 | -0.7 | 187065 | 27902233000 | 32821195371000 | 2.05 | 220276479 | NaN | NaN |
4 | 015760 | 한국전력 | 45650 | -450 | -1.0 | 439486 | 20161042650 | 29305660115050 | 1.83 | 641964077 | NaN | NaN |
date = datetime(2017, 3, 3).strftime('%Y%m%d')
df = stock_master_price(date)
df.head()
종목코드 | 종목명 | 현재가 | 대비 | 등락률 | 거래량 | 거래대금 | 시가총액 | 시가총액비중(%) | 상장주식수(천주) | 외국인 보유주식수 | 외국인 지분율(%) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 005930 | 삼성전자 | 1981000 | -5000 | -0.2 | 254174 | 500689858000 | 278685766597000 | 18.07 | 140679337 | 71175695 | 50.59 |
1 | 000660 | SK하이닉스 | 47100 | -600 | -1.3 | 3937032 | 186640393450 | 34288911391500 | 2.22 | 728002365 | 358720683 | 49.27 |
2 | 005935 | 삼성전자우 | 1545000 | -22000 | -1.4 | 60571 | 93097539000 | 31693244715000 | 2.05 | 20513427 | 15857741 | 77.30 |
3 | 005380 | 현대차 | 142000 | -6500 | -4.4 | 774281 | 110458431000 | 31279260018000 | 2.03 | 220276479 | 98462189 | 44.70 |
4 | 015760 | 한국전력 | 42950 | -200 | -0.5 | 1166862 | 49900115200 | 27572357107150 | 1.79 | 641964077 | 199597043 | 31.09 |
len(df)
2253
3. 거래소(KRX) 상장회사목록 크롤링 & DB update
트래픽 분석
시장정보 - 주식 - 상장현황 - 상장회사검색 - CSV 선택
두 단계에 걸쳐 진행됨.
- http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx
- http://file.krx.co.kr/download.jspx : GenerateOTP.jspx를 통해 리턴받은 값을 입력으로 사용한다.
데이터 가져오기
import pandas as pd
import numpy as np
import requests
import io
def get_krx_stock_master():
# STEP 01: Generate OTP
gen_otp_url = 'http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx'
gen_otp_data = {
'name':'fileDown',
'filetype':'xls',
'url':'MKD/04/0406/04060100/mkd04060100_01',
'market_gubun':'ALL', # ALL:전체
'isu_cdnm':'전체',
'sort_type':'A', # 정렬 : A 기업명
'std_ind_cd':'01',
'cpt':'1',
'in_cpt':'',
'in_cpt2':'',
'pagePath':'/contents/MKD/04/0406/04060100/MKD04060100.jsp',
} # Query String Parameters
r = requests.post(gen_otp_url, gen_otp_data)
code = r.content
# STEP 02: download
down_url = 'http://file.krx.co.kr/download.jspx'
down_data = {
'code': code,
}
r = requests.post(down_url, down_data)
f = io.BytesIO(r.content)
usecols = ['종목코드', '기업명', '업종코드', '업종']
df = pd.read_excel(f, converters={'종목코드': str, '업종코드': str}, usecols=usecols)
df.columns = ['code', 'name', 'sector_code', 'sector']
return df
df_master = get_krx_stock_master()
df_master.head()
code | name | sector_code | sector | |
---|---|---|---|---|
0 | 060310 | 3S | 032602 | 전자부품 제조업 |
1 | 095570 | AJ네트웍스 | 126903 | 산업용 기계 및 장비 임대업 |
2 | 068400 | AJ렌터카 | 126901 | 운송장비 임대업 |
3 | 006840 | AK홀딩스 | 137105 | 회사본부, 지주회사 및 경영컨설팅 서비스업 |
4 | 054620 | AP시스템 | 032902 | 특수 목적용 기계 제조업 |
Database Update
import mysql.connector
from sqlalchemy import create_engine
con_str = 'mysql+mysqlconnector://woosa7:finda***@localhost/findb'
engine = create_engine(con_str, echo=False)
insert_update_sql = """
insert into stock_master (code, name, sector_code, sector)
values (%s,%s,%s,%s)
on duplicate key update
code=values(code),
name=values(name),
sector_code=values(sector_code),
sector=values(sector)
"""
for ix, r in df_master.iterrows():
engine.execute(insert_update_sql, (r['code'], r['name'], r['sector_code'], r['sector']))
print(r['code'], r['name'])
060310 3S
095570 AJ네트웍스
068400 AJ렌터카
006840 AK홀딩스
054620 AP시스템
211270 AP위성
027410 BGF리테일
138930 BNK금융지주
001460 BYC
032040 C&S자산관리
001040 CJ
......
010240 흥국
189980 흥국에프엔비
000540 흥국화재
003280 흥아해운
037440 희림