ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [데이터수집] 내일은 휴장일? 한국거래소 확인 (2) 조회
    Python/텔레그램봇:채권모니터링 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()
    

     

    댓글

Designed by Tistory.