본문 바로가기
Python

Get 방식의 웹 서비스(Rest API) 호출하기 - json편

by 청양호박이 2020. 12. 17.

개발을 하다보면, 다 시스템에 필요한 데이터를 요청(Request)하고 그 결과를 응답(Response)을 받아 내부 로직에 적용하여 사용하는 일이 매우 많습니다. 얼마전에 글을 작성한 공공데이터포털이나 OPEN DART(전자공시시스템)에서도 개발자가 원하는 데이터를 웹 서비스로 제공하고 있습니다.

 

그렇다면, 이 데이터를 어떻게 호출해서 결과를 받아와 사용을 할 수 있는지 알아보겠습니다. 공공데이터포털에서 사용하고자 하는 Rest API를 사용해도 되고, OPEN DART에서 제공하는 API로 사용해도 됩니다. 저는 그래도 최근에 작성한 글과 관련하여 OPEN DART에서 제공하는 API를 가지고 구현해 보겠습니다.

 

Python에서는 기본적으로 웹자원을 바로 접근할 수 있는 모듈을 제공합니다. 

urllib는 URL 작업을 위한 여러 모듈을 모은 패키지로써, 

 

  • URL을 요청하기 위한 urllib.request
  • urllib.request에 의해 발생하는 예외에 대한 urllib.error
  • URL의 분석을 위한 urllib.parse
  • URL의 요청에 대한 응답을 처리하는건 urllib.request내 urlopen을 통해서 하기 때문에 별도 없음

 

로 구성되어 있습니다. 하지만 사용하기가 직관적이라고는 하기가 힘들어서 제 생각에는 직관적이라고 판단되는... 많이 사용되어지고 있는 requests 라는 모듈을 사용해 보도록 하겠습니다.

 

 

1. requests 설치


기본적으로 제공되는 모듈이 아니기 때문에, 별도로 설치를 하는 작업을 필요로 합니다. pypi.org에서 찾아보면, 아래와 같이 설치법과 사용법을 제공해 줍니다. 

 

그렇다면, 간단하게 설치를 해 줍니다. 

이제 사용할 준비를 마쳤습니다. 

 

 

2. requests 사용해보기 (get)


아무래도 get과 post방식은 요청하는 방식이 다르며, 이번에는 get만 다루어 보도록 하겠습니다. requests에서는 urllib보다 상당히 직관적입니다. request를 할때는 그냥 내가 원하는 방식을 메소드로 제공하고 있기 때문에 단순히 방식만 아래와 같이 사용하면 됩니다.

requests.get(URL, Param)

그리고, 내부 파라메터로는 url과 필수 input값들로 구성이 됩니다. 다음으로는, get으로 가져온 결과에 대해서 제공하는 메서드에 대해서 알아보게습니다. 

print(res.status_code)
print(res.headers['content-type'])
print(res.encoding)
print(res.text)
print(res.json())

 

  • status_code - get호출에 대한 정상/비정상 여부 코드를 반환합니다. (200 ok)
  • headers - get호출에 대한 결과 헤더 정보를 반환합니다.
  • encoding - get호출 결과값의 인코딩된 형태를 반환합니다. (ANSI, UTF-8, EUC-KR 등)
  • text - get호출 결과를 text로 반환합니다.
  • jons() - get호출 결과가 json으로 제공될 경우 자동으로 json타입으로 반환합니다.

 

이정도만 알면 바로 타 시스템에서 제공되는 Rest API를 호출해서 결과를 받아올 수 있습니다. 그렇다면 OPEN DART에서 제공하는 API를 하나 호출해서 받아와 보도록 하겠습니다.

 

 

[필요 정보]

url = 'https://opendart.fss.or.kr/api/fnlttSinglAcntAll.json'
params = {'crtfc_key':'<input my 인증키 infomation>',
          'corp_code':'00126380', 'bsns_year':'2020', 'reprt_code':'11014', 'fs_div':'CFS'}

출력포맷을 2가지를 제공하기 때문에 json으로 선택하여 진행해 보겠습니다. 해당 주소를 url 변수로 만들어 저장하고... 요청인자에 해당하는 5개 값을 별도의 params라는 dict형으로 만들어 저장해줍니다.

 

저는 00126380 이라는 고유번호를 가진 회사에 대해서, 2020년도 3분기보고서를 해당 회사뿐만아닌 지배구조에 포함된 회사를 포함한 연결재무제표를 받아오고자 합니다.

 

[소스 코드]

import requests

url = 'https://opendart.fss.or.kr/api/fnlttSinglAcntAll.json'
params = {'crtfc_key':'<input my 인증키 infomation>',
          'corp_code':'00126380', 'bsns_year':'2022', 'reprt_code':'11014', 'fs_div':'CFS'}

res = requests.get(url,params)

print(res.status_code)
print(res.headers['content-type'])
print(res.encoding)
print(res.text)
print(res.json())

print(len(res.json()['list']))

 

[관련정보]

200
application/json;charset=UTF-8
UTF-8
생략
아래 json결과 참조
183

해당 요청에 대한 status_code는 200 ok로 정상적으로 받아왔습니다. 그리고 header 및 encoding정보는 확인용으로 봐주시고... 중요한 결과는 아래의 json결과로 대체하겠습니다. 해당 URL로 API를 호출한 결과는 reqeusts로 인해서 아주 깔끔하게 json으로 변환되어 받아옵니다.

 

json의 구조는 대표적으로 입력값에 대한 결과를 status로 제공해주고... 이번 요청에는 000 / 정상입니다. 그리고 list로 각 재무제표항목에 대해서 제공을 해주는 방식입니다. 

print(len(res.json()['list']))

==============================
183

해당 list에 대해서 개수를 세어보면 총 183개 항목에 대해서 결과를 리턴해 주는 것을 확인할 수 있습니다.

 

[json 결과]

{'status': '000', 'message': '정상', 'list': [
    {'rcept_no': '20201116001248', 'reprt_code': '11014', 'bsns_year': '2020', 'corp_code': '00126380', 'sj_div': 'BS',
     'sj_nm': '재무상태표', 'account_id': 'ifrs-full_CurrentAssets', 'account_nm': '유동자산', 'account_detail': '-',
     'thstrm_nm': '제 52 기 3분기말', 'thstrm_amount': '203634913000000', 'frmtrm_nm': '제 51 기말',
     'frmtrm_amount': '181385260000000', 'ord': '1'},
    {'rcept_no': '20201116001248', 'reprt_code': '11014', 'bsns_year': '2020', 'corp_code': '00126380', 'sj_div': 'BS',
     'sj_nm': '재무상태표', 'account_id': 'ifrs-full_CashAndCashEquivalents', 'account_nm': '현금및현금성자산',
     'account_detail': '-', 'thstrm_nm': '제 52 기 3분기말', 'thstrm_amount': '26566097000000', 'frmtrm_nm': '제 51 기말',
     'frmtrm_amount': '26885999000000', 'ord': '2'},
    {'rcept_no': '20201116001248', 'reprt_code': '11014', 'bsns_year': '2020', 'corp_code': '00126380', 'sj_div': 'BS',
     'sj_nm': '재무상태표', 'account_id': 'dart_ShortTermDepositsNotClassifiedAsCashEquivalents', 'account_nm': '단기금융상품',
     'account_detail': '-', 'thstrm_nm': '제 52 기 3분기말', 'thstrm_amount': '89694025000000', 'frmtrm_nm': '제 51 기말',
     'frmtrm_amount': '76252052000000', 'ord': '3'},
    {'rcept_no': '20201116001248', 'reprt_code': '11014', 'bsns_year': '2020', 'corp_code': '00126380', 'sj_div': 'BS',
     'sj_nm': '재무상태표', 'account_id': '-표준계정코드 미사용-', 'account_nm': '단기상각후원가금융자산', 'account_detail': '-',
     'thstrm_nm': '제 52 기 3분기말', 'thstrm_amount': '1684068000000', 'frmtrm_nm': '제 51 기말',
     'frmtrm_amount': '3914216000000', 'ord': '4'},

이제 남은건 내가 원하는걸 마음껏 빼서 사용하면 되는 것입니다.

 

 

3. 이상값 제공시 결과


API호출시 입력값에 이상한 값을 넣었을때, 그 결과도 한번 보도록 하겠습니다.

 

[입력정보]

url = 'https://opendart.fss.or.kr/api/fnlttSinglAcntAll.json'
params = {'crtfc_key':'< >',
          'corp_code':'00126380', 'bsns_year':'2022', 'reprt_code':'11014', 'fs_div':'CFS'}

기존과 크게 다른점은 없고, 요청년도를 아직 도래하지 않은 2022년으로 설정하였습니다.

 

[결과]

200
application/json;charset=UTF-8
UTF-8
{"status":"013","message":"조회된 데이타가 없습니다."}
{'status': '013', 'message': '조회된 데이타가 없습니다.'}

여기서 한가지 주의할 점은... requests를 통한 get요청은 200 ok로 정상이지만, API 요청에 대한 정보제공 시스템 내부에서는 그 결과가 없기 때문에 status는 013으로 다른 결과를 제공하게 됩니다. 

 

API요청 자체에 대한 결과, API로직 수행 후 그에 대한 결과가 각 각 다르다고 보면 됩니다. 그럼 앞으로 다양한 곳에서 적용해 보세요~

 

- Ayotera Lab -

댓글