Python/텔레그램봇:채권모니터링

[데이터수집] 내일은 휴장일? 한국거래소 확인 (2) 조회

hayjo 2020. 12. 26. 21:03

봇을 돌리려면 오늘 휴장인지 정보가 필요하다.

해당 정보는 한국거래소 - MarketData - 시장정보 - 시장동향 - 증시일정 - 휴장일에서

  1) 엑셀파일로 다운로드 후 확인

  2) 조회 방식으로 확인

2가지 방법으로 확인이 가능하다.

 

조회도 파일다운로드처럼 OTP 발급과정을 거쳐서 처리하면 된다.

Nowtime값을 GenerateOTP에 전달 -> OTP 발급 -> OTP를 MKD99000001에 전달 -> 조회 데이터 리턴

조회에 필요한 Nowtime은 epoch time이므로 int(round(time.time() * 1000))을 정의해서 처리한다.


 

이번에는 다운로드 대신 조회 기능을 사용해볼 예정이다.

개발자 도구의 네트워크 부분을 열어보니 조회에는 Nowtime.jspx라는 단계가 하나 더 있다.

숫자가 epoch time 같긴 한데 뭔가 로직이 더 있는듯하다. 실제 찍어본 시간과는 약간 차이가 있다.

사이트에 접속하면 Nowtime.jspx가 실행되면서 현재 시간이 epoch time으로 전달되고,

그후에 다시 조회하면 10초 이상 지났는데도 아까 전달되었던 Nowtime 값에서 +1 식으로 갱신된다.

 

테스트 삼아 현재 epoch time을 보냈을 때 OTP가 정상 반환되었기 때문에, epoch time을 그대로 전달하는 방식을 썼다.

epoch time이 13자리로 전달되기 때문에 python에서 포맷을 작성하고

 

[참조] stackoverflow.com/questions/5998245/get-current-time-in-milliseconds-in-python

import time
t = lambda: int(round(time.time() * 1000))
print(t()) # 1608526699266

 

GenerateOTP를 실행한다.

import requests
import time

nowTime = lambda: str(int(round(time.time() * 1000))) # url로 보내야해서 str 한번 더 씌움

otp_headers = {'User-Agent': 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950)',
                'Referer': 'http://marketdata.krx.co.kr/contents/MKD/01/0110/01100305/MKD01100305.jsp'
              }
otpURL = 'http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx?bld=MKD/01/0110/01100305/mkd01100305_01&name=form&_='

otp = requests.get(url=otpURL + nowTime(), headers=otp_headers)

# print(otp.content)

otpURL과 headers의 Referer 정보는 Network에서 GenerateOTP 파일의 url을 확인해서 얻었다.

OTP 확인이 완료되었으니, MKD99000001에 요청을 보내본다. 역시 post 요청이기 때문에 정보를 form data로 보내줘야 한다. 

호출시마다 search_bas_yy를 갱신해야 하므로 함수로 구성했다.

* 엑셀로 다운로드 할 때는 MKD99000001가 아니라 GenerateOTP 때 gridTp, search_bas_yy, pagePath 변수를 전달해서, 단순 url 쿼리스트링 복사로 처리했었다.

 

download_headers = {'User-Agent': 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950)',
                 'Referer': 'http://marketdata.krx.co.kr/mdi'
               }

def getFormData():
    return {
               'gridTp': "KRX",
               'search_bas_yy': str(time.gmtime().tm_year), # '2020' # 년도
               'code': otp.content,  # 위에서 획득한 OTP를 여기 넣어주자
               'pagePath': '/contents/MKD/01/0110/01100305/MKD01100305.jsp'
             }
             
downloadURL = 'http://marketdata.krx.co.kr/contents/MKD/99/MKD99000001.jspx'

data = requests.get(downloadURL, getFormData(), headers=download_headers)
print(data.json()) # 데이터는 제이슨 타입으로 들어온다

예쁘게 잘 나온다.

일자 및 요일의 리스트만 필요하다면

jsonData = data.json()
print([each['calnd_dd_dy'] for each in jsonData['block1']])
'''
['2020-01-01', '2020-01-24', '2020-01-27', '2020-04-15', '2020-04-30', '2020-05-01', '2020-05-05', '2020-08-17', '2020-09-30', '2020-10-01', '2020-1
0-02', '2020-10-09', '2020-12-25', '2020-12-31']
'''

 

 

 

# 전체 코드

import requests
import time

userAgent = 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950)'
# otp url 정보
otpReferer = 'http://marketdata.krx.co.kr/contents/MKD/01/0110/01100305/MKD01100305.jsp'
otpURL = 'http://marketdata.krx.co.kr/contents/COM/GenerateOTP.jspx?bld=MKD/01/0110/01100305/mkd01100305_01&name=form&_='
# view url 정보
viewReferer = 'http://marketdata.krx.co.kr/mdi'
viewURL = 'http://marketdata.krx.co.kr/contents/MKD/99/MKD99000001.jspx'

otp_headers = {
                'User-Agent': userAgent,
                'Referer': otpReferer
              }
view_headers = {
                 'User-Agent': userAgent,
                 'Referer': viewReferer
               }


def getOTP(otpURL, otp_headers):
    nowTime = str(int(round(time.time() * 1000))) # 함수 안에 넣으면서 람다를 지웠다
    otp = requests.get(url=otpURL + nowTime, headers=otp_headers)
    return otp.content


def getFormData(OTP):
    return {
               'gridTp': "KRX",
               'search_bas_yy': str(time.gmtime().tm_year),  # '2020' # 년도
               'code': OTP,  # 위에서 획득한 OTP를 여기 넣어주자
               'pagePath': '/contents/MKD/01/0110/01100305/MKD01100305.jsp'
             }


def getData(viewURL, FormData, view_headers):
    return requests.get(viewURL, FormData, headers=view_headers)


def getHolidayList(otp_headers, view_headers, otpURL, viewURL):
    OTP = getOTP(otpURL, otp_headers)
    time.sleep(1)
    formData = getFormData(OTP)
    data = getData(viewURL, formData, view_headers).json()
    return [each['calnd_dd_dy'] for each in data['block1']]


def main():
    hList = getHolidayList(otp_headers, view_headers, otpURL, viewURL)
    print(hList)


if __name__ == '__main__':
    main()