2020년 3월 19일 목요일

python: 공적 마스크 판매정도 시각화 (feat.folium)

Untitled

공적 마스크 API를 사용해 동네 약국정보를 표시해 보자

1. API 명세를 확인

위도와 경보를 통해 판매정보를 가져올 수도 있고 주소를 통해 가져올 수도 있다.
다만 주소의 경우 정확한 주소를 입력해야 한다.

1.1 API Test

In [1]:
import json, requests
url = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByAddr/json?address=서울특별시 송파구 잠실동'
result = json.loads(str(requests.get(url).text))
result['stores'][:5]
Out[1]:
[{'addr': '서울특별시 송파구 백제고분로12길 17 (잠실동)',
  'code': '11805714',
  'created_at': '2020/03/20 10:40:00',
  'lat': 37.5046028,
  'lng': 127.0807043,
  'name': '온누리건강약국',
  'remain_stat': 'empty',
  'stock_at': '2020/03/19 10:48:00',
  'type': '01'},
 {'addr': '서울특별시 송파구 올림픽로 203 (잠실동, 중앙상가 150호)',
  'code': '11810122',
  'created_at': '2020/03/20 10:40:00',
  'lat': 37.5124982,
  'lng': 127.0933434,
  'name': '영림약국',
  'remain_stat': 'empty',
  'stock_at': '2020/03/19 13:14:00',
  'type': '01'},
 {'addr': '서울특별시 송파구 올림픽로 212 (잠실동, 갤러리아팰리스 2층)',
  'code': '11810131',
  'created_at': None,
  'lat': 37.5111896,
  'lng': 127.0939713,
  'name': '참사랑약국',
  'remain_stat': None,
  'stock_at': None,
  'type': '01'},
 {'addr': '서울특별시 송파구 올림픽로 212 2층 220호 (잠실동, 갤러리아팰리스)',
  'code': '11827700',
  'created_at': '2020/03/20 10:40:00',
  'lat': 37.5111896,
  'lng': 127.0939713,
  'name': '메디팜양의약국',
  'remain_stat': 'empty',
  'stock_at': '2020/03/20 09:19:00',
  'type': '01'},
 {'addr': '서울특별시 송파구 올림픽로 76 1층 104-1호 (잠실동, J타워)',
  'code': '11827815',
  'created_at': '2020/03/20 10:40:00',
  'lat': 37.5115631,
  'lng': 127.0792026,
  'name': '다인약국',
  'remain_stat': 'empty',
  'stock_at': '2020/03/19 12:13:00',
  'type': '01'}]

2. 특정 위치에 지도를 그려보자

folium 패키지를 활용해서 지도를 출력한다.
In [2]:
import folium

좌표=(37.5119564733933, 127.088282780728)
 
map_osm = folium.Map(location=좌표, zoom_start=15)
folium.Marker(좌표, popup='잠실'.encode('utf-8')).add_to(map_osm)
map_osm
# jupyter notebook에서는 한글이 깨져서 출력된다.
Out[2]:
In [3]:
#save를 하면 이상없이 정상 출력 된다.
map_osm.save('folium.html')

2.1 한글명을 영문명으로 변경하기 위해 naver api를 활용해 변경한다.

In [4]:
import urllib.request

def getRomanCharacters(_str):

    _client_id = "YOUR_CLIENT_ID"
    _client_secret = "YOUR_CLIENT_SECRET"

    # API가 7자리 이상인 경우 결과값이 없음 --> 예외처리
    _addStr= ''
    if ( len(_str) > 7 ) :
        _str = _str[:7]
        _addStr = '...'    

    encText = urllib.parse.quote(_str)
    
    url = "https://openapi.naver.com/v1/krdict/romanization?query=" + encText

    request = urllib.request.Request(url)
    request.add_header("X-Naver-Client-Id",_client_id)
    request.add_header("X-Naver-Client-Secret",_client_secret)
    response = urllib.request.urlopen(request)
    rescode = response.getcode()

    if(rescode==200):
        response_body = response.read()
        jsData = json.loads(response_body)
        if( len(jsData['aResult']) > 0 ):
            first_string = jsData['aResult'][0]['aItems'][0]['name']
        else:
            first_string = "-"
        return first_string.replace(' ','') + _addStr
    else:
        print("Error Code:" + rescode)
        return '-'
    
    
getRomanCharacters('가나다')
Out[4]:
'GaNada'

3. 동네 약국 정보를 가져와 지도에 출력해 보자

In [5]:
url = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByAddr/json?address=서울특별시 송파구 잠실동'
result = json.loads(str(requests.get(url).text))
결과를 받아와 위도,경도,마스크 남은 수를 sotres에 저장
In [6]:
stores = []
for x in result['stores']:
    name = getRomanCharacters(x['name'])
    lat = x['lat']
    lng = x['lng']
    if 'remain_stat' in x.keys():
        remain = x['remain_stat']
    else:
        remain = 'break'
    stores.append([name, lat, lng, remain])
In [7]:
# 재고 상태[100개 이상(녹색): 'plenty' / 30개 이상 100개미만(노랑색): 'some' / 2개 이상 30개 미만(빨강색): 'few' / 1개 이하(회색): 'empty' / 판매중지: 'break']
colorDic={'plenty':'green', 'empty':'gray', 'few':'red', 'some':'beige','break':'black',None:'black'}
In [9]:
loc = (37.5119564733933, 127.088282780728)
map_osm = folium.Map(location=loc, zoom_start=15)

for x in stores:
    
    location = (x[1],x[2])
    cnt = x[3]
    name = x[0]
    popStr = name + '(' + str(cnt) + ')'
    folium.Marker(location, popup=popStr, icon=folium.Icon(color=colorDic[cnt])).add_to(map_osm)
map_osm
Out[9]:

댓글 없음:

댓글 쓰기

추천 게시물

python: SVD(Singular Value Decomposition)로 간단한 추천시스템 만들기( feat. surprise )

svd_example In [15]: # !pip install surprise In [21]: from...