본문 바로가기
Developer/Python

[Python] 공적 마스크 API 활용하여 지도로 구현하기 (Folium 라이브러리 적용)

by Doony 2020. 3. 16.

얼마 전 공적 마스크 실시간 재고확인을 위한 공공 API가 오픈되었습니다. 간단히 API를 호출하여 재고를 나타내는 방법을 파이썬을 이용하여 구현해보도록 하겠습니다.


순서

  • API를 통한 데이터 로드
  • Folium을 이용한 지도 표기 (라이브러리 사용법은 여기에서 확인가능)

API 호출 코드 설명

  • 공공 API 활용은 공공데이터포털에서 상세히 확인할 수 있습니다. 그 중에서도 공적 마스크 재고는 여기에서 확인하실 수 있습니다.

  • API페이지에서 상세 조회가 가능하며, 이 포스팅에서는 그 중 /storesByGeo/json 주소를 통해 데이터를 받는 것으로 진행합니다.

  • 원하는 위도/경도 및 반경을 쿼리값으로 넣어 호출하면, 그에 해당하는 약국리스트와 재고량 및 업데이트 시간 등을 반환해줍니다. (코드에서는 사당역 위도/경도를 넣었습니다.)

  • 반환된 데이터는 json 형태로 되어 있으며, 각 항목별로 리스트에 추가합니다.

  • 데이터가 필드값이 아예 없는 경우가 있어서, 예외처리를 해줬습니다.

    Folium 코드 설명

  • circle를 이용해 각 약국별 위도/경도 정보를 원으로 나타냈습니다.

  • 재고량에 따라 정부에서 권고한대로 색상표기를 해줬습니다. 색상은 colorSelection이라는 함수를 만들어 사용했습니다.

  • 원 클릭 시, 해당 약국에 대한 정보를 보여주기 위해 popUp을 띄우고, 재고량은 transformToNum 함수를 통해 표기했습니다.


코드 실행 시, folium 맵에 약국 좌표들이 나타나는 것을 볼 수 있습니다. 또한 점 클릭 시, 해당 약국에 대한 상세 정보를 확인할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def colorSelection(text):
    if text == 'empty':
        color = '#8C8C8C'
    elif text == 'few':
        color = '#FF0000'
    elif text == 'some':
        color = '#FFBB00'
    elif text == 'plenty':
        color = '#2F9D27'
    else:
        color = '#000000'
    return color
 
def transformToNum(text):
    if text == 'empty':
        number = '0~1개'
    elif text == 'few':
        number = '2~29개'
    elif text == 'some':
        number = '30~99개'
    elif text == 'plenty':
        number = '100개 이상'
    else:
        number = '불분명'
    return number
 
 
import requests
import folium
 
# 사당역 중심에서 15 zoom으로 시작. tiles는 기호에 따라 설정 37.392132, 126.957943
= folium.Map((37.392132126.957943), tiles='Cartodb Positron', zoom_start= 15)
 
URL = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByGeo/json'
 
# 초기에는 사당역 중심, 반경 3키로 이내 검색
params = {'lat'37.476578'lng'126.981625'm'3000}
response = requests.get(URL,params=params)
 
# 전체 검색된 약국의 수. 
print(response)
total_pages = response.json()["count"]
store = response.json()["stores"]
 
# 리스트 초기화
addr = []
lat = []
lng = []
name = []
remain_stat = []
remain_number = []
stock_at = []
created_at = []
 
# 검색된 내용을 리스트에 담기
for i in range(len(store)):
    if len(store[i]) == 9:
        if store[i]["remain_stat"is None:
            remain_stat.append("재고 불분명")
            remain_number.append("재고 불분명")
        else:
            remain_stat.append(store[i]["remain_stat"])
            remain_number.append(transformToNum(store[i]["remain_stat"]))
            
            
 
        if store[i]["addr"is None:
            addr.append(store[i]["error"])
        else:
            addr.append(store[i]["addr"])
 
            
        if store[i]["lat"is None:
            lat.append(0)
        else:
            lat.append(store[i]["lat"])
 
 
 
        if store[i]["lng"is None:
            lng.append(0)
        else:
            lng.append(store[i]["lng"])
 
 
 
        if store[i]["name"is None:
            name.append("이름 없음")
        else:
            name.append(store[i]["name"])
 
  
 
        if store[i]["stock_at"is None:
            stock_at.append("입고시간 없음")
        else:
            stock_at.append(store[i]["stock_at"])
        
        if store[i]["created_at"is None:
            created_at.append("업데이트 시간 없음")
        else:
            created_at.append(store[i]["created_at"])
 
    else:
        print("정보가 이상함. 서버문제.")
 
 
for i in range(len(lat)):
    folium.Circle(
        location = [lat[i], lng[i]],
        radius = 20,
        color = colorSelection(remain_stat[i]),
        fill = 'crimson',
        popup=folium.Popup('<strong>' + name[i]+'</strong><br>'+
                           '재고수량: ' + remain_number[i] + '<br>' +
                           '입고시간: ' + stock_at[i] + '<br>' +
                           '업데이트: ' + created_at[i], parse_html=False, max_width = 300)
    ).add_to(m)
 
m
cs

댓글