오리는짹짹 2023. 1. 9. 15:37
목차
1. 웹 API의 이해
2. 정부의 공공 데이터 가져오기

1. 웹 API의 이해

  • API (Application Programming Interface)
    : 응용 프로그램에서 사용할 수 있도록 기능을 제어할 수 있게 만든 인터페이스
  • 웹 API
    : 웹 어플리케이션 개발에서 다른 서비스에 요청을 보내고 응답을 받기 위해 정의된 명세
    (www.programmableweb.com/category/all/apis)

1. 웹 API의 데이터 획득 과정

정보를 요청하면 원하는 데이터를 전송한다.

  • REST (Representational State Transfer) API = 요청하면 응답 후 연결을 끊음
  • Streaming API = 강제로 연결을 끊기 전까지 연결함

2. 웹 API의 인증 방식

  •  인증이 필요한 경우, 여러가지 방법으로 인증을 요구하는 경우가 있음
  • 최근에는 대부분이 Open Authorization 방식을 사용함 (API키, 접속토큰)을 이용해 권한을 부여함
  • 다른 사람에게 공개해선 안되며, 공개할 경우 재신청 해야 함

3. 응답 데이터의 형식 및 처리

: JSON, XML = 웹 서버에서 클라이언트로 데이터를 전달하기 위해 만든 구조화딘 텍스트 형식

(1) JSON 형식의 데이터 처리

  • JSON (Javascript Object Notation)
    데이터 하나의 집합을 객체 (Object)라고 하며 '이름(name):값(value)'로 구분
import json

python_dict = {
    "이름" : "홍길동",
    "나이" : 25,
    "거주지" : "서울",
    "신체정보" : {
        "키" : 175.4,
        "몸무게" : 71.2
    },
    "취미" : [
        "등산",
        "자전거타기",
        "독서"
    ]
}

type(python_dict)
>>> dict

👀 JSON 뷰어 (http://jsonviewer.stack.hu/)

  • 파이썬을 JSON 형태로 변환
json_data = json.dumps(python_dict)

type(json_data)
>>> str
print(json_data)

>>> {"\uc774\ub984": "\ud64d\uae38\ub3d9", "\ub098\uc774": 25, "\uac70\uc8fc\uc9c0": "\uc11c\uc6b8", "\uc2e0\uccb4\uc815\ubcf4": {"\ud0a4": 175.4, "\ubab8\ubb34\uac8c": 71.2}, "\ucde8\ubbf8": ["\ub4f1\uc0b0", "\uc790\uc804\uac70\ud0c0\uae30", "\ub3c5\uc11c"]}
  • 옵션을 추가해서 출력 (들여쓰기, 딕셔너리 일 경우 키를 기준으로 정렬, 아스키 코드로 구성된 문자열 설정 (한글 = false)
json_data = json.dumps(python_dict, indent = 3, sort_keys = True, ensure_ascii=False)

print(json_data)
>>> {
       "거주지": "서울",
       "나이": 25,
       "신체정보": {
          "몸무게": 71.2,
          "키": 175.4
       },
       "이름": "홍길동",
       "취미": [
          "등산",
          "자전거타기",
          "독서"
       ]
    }
  •  json을 파이썬의 딕셔너리 형태로 변환
json_dict = json.loads(json_data)

type(json_dict)
>>> dict
  • JSON에서 정보 추출
json_dict['신체정보']['몸무게']
>>> 71.2

json_dict['취미']
>>> ['등산', '자전거타기', '독서']

json_dict['취미'][0]
>>> '등산'

(2) XML 형식의 데이터 처리

  • xml 예제
xml_data = """<?xml version="1.0" encoding="UTF-8" ?>
<사용자정보>
    <이름>홍길동</이름>
    <나이>25</나이>
    <거주지>서울</거주지>
    <신체정보>
        <키 unit="cm">175.4</키>
        <몸무게 unit="kg">71.2</몸무게>
    </신체정보>
    <취미>등산</취미>
    <취미>자전거타기</취미>
    <취미>독서</취미>
</사용자정보>
"""

print(xml_data)
>>> <?xml version="1.0" encoding="UTF-8" ?>
    <사용자정보>
        <이름>홍길동</이름>
        <나이>25</나이>
        <거주지>서울</거주지>
        <신체정보>
            <키 unit="cm">175.4</키>
            <몸무게 unit="kg">71.2</몸무게>
        </신체정보>
        <취미>등산</취미>
        <취미>자전거타기</취미>
        <취미>독서</취미>
    </사용자정보>
  • 파이썬의 딕셔너리 타입의 데이터 (속성 '@속성이름', 태그의문자열'#text')로 출력
import xmltodict # 딕셔너리로 변환

dict_data = xmltodict.parse(xml_data, xml_attribs=True)
dict_data
>>> {'사용자정보': {'이름': '홍길동',
      '나이': '25',
      '거주지': '서울',
      '신체정보': {'키': {'@unit': 'cm', '#text': '175.4'},
       '몸무게': {'@unit': 'kg', '#text': '71.2'}},
      '취미': ['등산', '자전거타기', '독서']}}
  • 사용자 정보 중 이름을 알고 싶을 때
dict_data['사용자정보']['이름']
>>> '홍길동'

dict_data['사용자정보']['신체정보']
>>> {'키': {'@unit': 'cm', '#text': '175.4'},
     '몸무게': {'@unit': 'kg', '#text': '71.2'}}
  • 키의 속성과 문자열을 출력하고 싶을 때
dict_data['사용자정보']['신체정보']['키']['@unit']
>>> 'cm'

dict_data['사용자정보']['신체정보']['키']['#text']
>>> '175.4'
  • XML 데이터에서 원하는 데이터를 추출
import xmltodict

dict_data = xmltodict.parse(xml_data)

user_name = dict_data['사용자정보']['이름']
body_data = dict_data['사용자정보']['신체정보']

height = body_data ['키']['#text']
height_unit = body_data ['키']['@unit']

weight = body_data ['몸무게']['#text']
weight_unit = body_data ['몸무게']['@unit']

print(f"[사용자 {'user_name'}의 신체정보]")
print("*키: {0}{1}".format(height, height_unit))
print("*몸무게: {0}{1}".format(weight, weight_unit))


>>> [사용자 user_name의 신체정보]
    *키: 175.4cm
    *몸무게: 71.2kg
  • xml_attribs = False 선택시
dict_data2 = xmltodict.parse(xml_data, xml_attribs = False)
dict_data2
>>> {'사용자정보': {'이름': '홍길동',
      '나이': '25',
      '거주지': '서울',
      '신체정보': {'키': '175.4', '몸무게': '71.2'},
      '취미': ['등산', '자전거타기', '독서']}}

 

 

2. 정부의 공공 데이터 가져오기

: 도로명 주소와 우편번호 추출하기

1. 내 인증키를 변수 API_KEY로 지정

import requests

API_KEY = 'Encoding 주소를 적어보시죠(o゜▽゜)o☆'
API_KEY_decode = requests.utils.unquote(API_KEY)

API_KEY_decode
>>> 'Decoding 인증키 촤르르 (∩^o^)⊃━☆'

2. 도로명 주소를 지정해 데이터 가져오기

req_url = "http://openapi.epost.go.kr/postal/retrieveNewAdressAreaCdService/retrieveNewAdressAreaCdService/getNewAddressListAreaCd"

search_Se = "road"
srch_wrd = "반포대로 201"

req_parameter = {"ServiceKey":API_KEY_decode, "searchSe":search_Se, "srchwrd":srch_wrd}

r = requests.get(req_url, params = req_parameter)
xml_data = r.text

print(xml_data)
>>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?><NewAddressListResponse><cmmMsgHeader><requestMsgId></requestMsgId><responseMsgId></responseMsgId><responseTime>20230109:144911640</responseTime><successYN>Y</successYN><returnCode>00</returnCode><errMsg></errMsg><totalCount>1</totalCount><countPerPage>10</countPerPage><totalPage>1</totalPage><currentPage></currentPage></cmmMsgHeader><newAddressListAreaCd><zipNo>06579</zipNo><lnmAdres>서울특별시 서초구 반포대로 201 (반포동, 국립중앙도서관)</lnmAdres><rnAdres>서울특별시 서초구 반포동 산60-1 국립중앙도서관</rnAdres></newAddressListAreaCd></NewAddressListResponse>

3. xmltodict 라이브러리로 딕셔너리 데이터로 변환

import xmltodict

dict_data = xmltodict.parse(xml_data)

dict_data
>>> {'NewAddressListResponse': {'cmmMsgHeader': {'requestMsgId': None,
   'responseMsgId': None,
   'responseTime': '20230109:144911640',
   'successYN': 'Y',
   'returnCode': '00',
   'errMsg': None,
   'totalCount': '1',
   'countPerPage': '10',
   'totalPage': '1',
   'currentPage': None},
  'newAddressListAreaCd': {'zipNo': '06579',
   'lnmAdres': '서울특별시 서초구 반포대로 201 (반포동, 국립중앙도서관)',
   'rnAdres': '서울특별시 서초구 반포동 산60-1 국립중앙도서관'}}}

4. 원하는 값 추출하기

adress_list = dict_data['NewAddressListResponse']['newAddressListAreaCd']

print("[입력한 도로명 주소]", srch_wrd)
print("[응답 데이터에서 추출한 결과]")
print("- 우편번호:", adress_list['zipNo'])
print("- 도로명주소:", adress_list['lnmAdres'])
print("- 지번 주소:",adress_list['rnAdres'])

>>> [입력한 도로명 주소] 반포대로 201
>>> [응답 데이터에서 추출한 결과]
>>> - 우편번호: 06579
>>> - 도로명주소: 서울특별시 서초구 반포대로 201 (반포동, 국립중앙도서관)
>>> - 지번 주소: 서울특별시 서초구 반포동 산60-1 국립중앙도서관