ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [PlayData - Day 14] 웹 API
    [플레이데이터] 2023. 1. 12. 11:13

    1. K-Digital Training 과정

    • 빅데이터 기반 지능형SW 및 MLOps 개발자 양성과정 19기 (2023/01/09 - Day 14)

    2. 목차

    1. 웹 API의 이해
    2. 정부의 공공 데이터 가져오기

    3. 수업 내용

    1. 웹 API의 이해

     

    API (Application Programming Interface)
    응용 프로그램에서 사용할 수 있도록 기능을 제어할 수 있게 만든 인터페이스

     

    웹 API
    웹 어플리케이션 개발에서 다른 서비스에 요청을 보내 응답을 받기 위해 정의된 명세
    어떤 웹사이트에서 어떤 API를 제공하는지를 정리한 사이트 (www.programmableweb.com/category/all/apis)

     

    웹 API의 데이터 획득 과정

    정보를 요청하면 원하는 데이터를 전송한다.
    REST(Representational State Transfer) API = 요청하면 응답 후 연결을 끊음
    Streaming API = 강제로 연결을 끊기 전까지 연결을 유지함

     

    웹 API의 인증 방식

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

    응답 데이터의 형식 및 처리

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

     

    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)
    print(type(json_data))
    print(json_data) # 이걸로 출력된 데이터를 복사해서 JSON 뷰어에 입력해도 똑같이 보여준다.
    
    >>>
    <class 'str'>
    {"\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"]}

    옵션을 추가해서 출력 (들여쓰기, 딕셔너리일 경우 Key를 기준으로 정렬, 아스키코드로 구성된 문자열을 설정(한글 = 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)
    print(type(json_dict))
    print(json_dict['신체정보']['몸무게'])
    print(json_dict['취미'])
    print(json_dict['취미'][0])
    
    >>> 
    <class 'dict'>
    71.2
    ['등산', '자전거타기', '독서']
    등산

    XML 형식의 데이터 처리
    XML (eXtensible Markup Language) 다목적 마크업 언어로 태그(Tag)를 사용

    !pip install xmltodict
    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 = xmltodict.parse(xml_data, xml_attribs=False)
    dict_data
    
    >>> #True와 False의 차이
    {'사용자정보': {'이름': '홍길동',
      '나이': '25',
      '거주지': '서울',
      '신체정보': {'키': '175.4', '몸무게': '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 데이터에서 원하는 데이터 추출

    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("[사용자 {0}의 신체정보]".format(user_name))
    print("*키: {0}{1}".format(height, height_unit))
    print("*몸무게: {0}{1}".format(weight, weight_unit))
    
    >>>
    [사용자 홍길동의 신체정보]
    *키: 175.4cm
    *몸무게: 71.2kg

    xml_attribs = False 선택시, unit값이 사라지고 dictionary 형태로 변환된다.
    JSON 형식과 유사

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

     

    # 2, 3번은 pass

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

    회원 가입 및 서비스 신청

    주소 및 우편번호 가져오기

    공공 데이터 포털(www.data.go.kr/ )에서 인증키 받기

    1. 접속 후 회원가입
    2. 회원가입 후 로그인
    3. 데이터 찾기에서 '도로명주소조회' 검색
    4. 활용신청(심의 승인의 경우 오랜 시간이 걸릴 수 있으므로 주의)
    5. 마이페이지에서 인증키 확인 및 참고문서 다운로드
    import requests
    
    API_KEY  = 'KEY' # 자신의 인증키를 복사해서 입력합니다.
    API_KEY_decode = requests.utils.unquote(API_KEY)
    API_KEY_decode
    req_url = "http://openapi.epost.go.kr/postal/retrieveNewAdressAreaCdService/retrieveNewAdressAreaCdService/getNewAddressListAreaCd"
    
    search_Se = "road" 
    srch_wrd = "세종로17"
    
    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)

    dict_data = xmltodict.parse(xml_data)
    dict_data

    adress_list = dict_data['NewAddressListResponse']['newAddressListAreaCd']
    
    print("[입력한 도로명 주소]", srch_wrd)
    print("[응답 데이터에서 추출한 결과]")
    print("- 우편번호:", adress_list[0]['zipNo']) # 여러 개의 검색결과가 나온 경우, 리스트의 위치값[0]을 지정해줘야한다.
    print("- 도로명 주소:", adress_list[0]['lnmAdres'])
    print("- 지번 주소:", adress_list[0]['rnAdres'])

    # 여러개의 검색 결과가 있을 경우 전부 프린트하기 위한 코드 (직접 수정)
    adress_list = dict_data['NewAddressListResponse']['newAddressListAreaCd']
    
    print("[입력한 도로명 주소]", srch_wrd)
    print("[응답 데이터에서 추출한 결과]")
    for adres in adress_list:
        print("- 우편번호:", adres['zipNo'])
        print("- 도로명 주소:", adres['lnmAdres'])
        print("- 지번 주소:", adres['rnAdres'])
        print("-----------------------------------------------------------------")

    댓글

Designed by Tistory.