데이터 엔지니어링 과정/python
[14일차] 웹 API
오리는짹짹
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 국립중앙도서관