OkBublewrap

API(3) 본문

Python/학습용

API(3)

옥뽁뽁 2023. 3. 21. 01:10

https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15073861 

 

한국환경공단_에어코리아_대기오염정보

각 측정소별 대기오염정보를 조회하기 위한 서비스로 기간별, 시도별 대기오염 정보와 통합대기환경지수 나쁨 이상 측정소 내역, 대기질(미세먼지/오존) 예보 통보 내역 등을 조회할 수 있다.

www.data.go.kr

위 api를 들고 와봤다. 정보를 찾으면서 구동은 되는데 남들 쓰는 게 다양해서 조금 시간이 걸렸다.

 

import requests

encoding = ''
decoding = ''

url = 'http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty'
Params = {
    'sidoName' : '부산',
    'pageNo' : '1',
    'numOfRows' : '100',
    'returnType' : 'XML',
    'serviceKey' : encoding,
    'ver' : '1.0'
}

response = requests.get(url, params = Params)
response.content

response.content로 진행을 했을 때 한글이 깨져서 나온다. 한글로 변형하기 위해서 인코딩을 변경을 해준다.

 

response_encoding = str(response.content, 'utf-8')
response_encoding
<?xml version="1.0" encoding="UTF-8"?>\r\n<response>\n  <header>\n    <resultCode>00</resultCode>\n    <resultMsg>NORMAL_CODE</resultMsg>\n  </header>\n  <body>\n    <items>\n      <item>\n        <so2Grade>1</so2Grade>\n        <coFlag/>\n        <khaiValue>72</khaiValue>\n        <so2Value>0.003</so2Value>\n        <coValue>0.4</coValue>\n        <pm25Flag/>\n        <pm10Flag/>\n        <o3Grade>2</o3Grade>\n        <pm10Value>50</pm10Value>\n        <khaiGrade>2</khaiGrade>\n        <pm25Value>18</pm25Value>\n        <sidoName>부산</sidoName>\n        <no2Flag/>\n        <no2Grade>1</no2Grade>\n        <o3Flag/>\n        <pm25Grade>2</pm25Grade>\n        <so2Flag/>\n...

 

보기 좋게 변형 Dict

import xmltodict

dict_data = xmltodict.parse(response_encoding, xml_attribs=True)
dict_data

우선 관측대가 있는 곳을 확인을 하기 위해서 sidoname만 추출해서 보기로했다.

 

len(dict_data['response']['body']['items']['item'])

35개 나왔다. 부산에는 총 35개의 관측소가 있다

 

for i in range(35):
    print(dict_data['response']['body']['items']['item'][i]['stationName'])
광복동
초량동
태종대
청학동
전포동
온천동
명장동
대연동
용호동
학장동
덕천동
화명동
삼락동
개금동
당리동
부산항
부산신항
부산북항
부산감만
청룡동
좌동
재송동
장림동
대저동
녹산동
명지동
연산동
기장읍
용수리
수정동
부곡동
회동동
광안동
대신동
덕포동

 

데이터 프레임 만들기

stationName을 인덱스로 넣고 행에는 여러가지변수중 종합적인 지수, 수치만 들고 오기로 했다. 

우선 첫번째에 있는 광복동에 있는 수치를 들고오면 다음과 같다.

dict_data['response']['body']['items']['item']['khaiValue']
# 72

dict_data['response']['body']['items']['item'][0]['khaiGrade']
# 2

KhaiGrade는 등급은 이렇게 사용이 된다. 광북동은 보통이다.

등급 좋음 보통 나쁨 매우나쁨
Grade 1 2 3 4
# index 
index = []
for i in range(35):
    index.append(dict_data['response']['body']['items']['item'][i]['stationName'])

khaiValue = []
for i in range(35):
    khaiValue.append(dict_data['response']['body']['items']['item'][i]['khaiValue'])
    
khaiGrade = []
for i in range(35):
    khaiGrade.append(dict_data['response']['body']['items']['item'][i]['khaiGrade'])
# DataFrame
import pandas as pd
df_khai = pd.DataFrame({
    'khaiValue' : khaiValue,
    'khaiGrade' : khaiGrade
}, index = index
)
df_khai.head(10)

df_khai.tail(10)

다 지수들은 보통으로 나왔다. 위치상 크게 다르지 않아서 그런 것 같다.

부산항이 khaiValue : -, khaiGrade는 None으로 나왔다. 오류거나 장비 점검중인 것 같다. 

# 부산에서 높은 값
df_khai.sort_values('khaiValue').tail(5)

# 부산에서 낮은 값
df_khai.sort_values('khaiValue').head(5)

khaiValue가 20이상 차이가 난 것을 볼 수 가있는데 위치를 보기 위해서 저번에 사용했던 folium을 사용해서 지도에서 표시를 할 것 이다. 우선 지도에 표기하기 위해서는 위도, 경도로 변환을 시켜 줘야 한다. 검색을 해보니 geo코딩을 통해서 좌표를 변환 시킬 수가 있었다. 우선 중심점을 표기하기 위해서 구글에서 검색한 좌표 

from geopy.geocoders import Nominatim

def geocoding(address):
    geolocoder = Nominatim(user_agent = 'South Korea', timeout=None)
    geo = geolocoder.geocode(address)
    crd = {"lat": str(geo.latitude), "lng": str(geo.longitude)}

    return crd

crd = geocoding("부산 전포동")
print(crd['lat'])
print(crd['lng'])

부산 전포동을 위도, 경도 표시 

35.1572828
129.0745022

위도 값 따로 경도값 따로 모아서 출력을 진행을 해야한다. 

 

lat = []
lng = []
for i in range(35):
    station_name = "부산 " + index[i]
    crd = geocoding(station_name)
    #lat.append(crd['lat'])
    #lng.append(crd['lng'])

코드를 작성을 하는 도중 오류가 발생이 됬다. 주소명이 위도, 경도를 못찾은 경우에 이 오류가 발생한다고 한다. 주소를 가져오지 못하는 주소는 오류로 처리를 해서 넘어가게 코드를 작성을 했다. 

lat = []
lng = []
for i in range(35):
    try:
        station_name = "부산 " + index[i]
        crd = geocoding(station_name)
        lat.append(crd['lat'])
        lng.append(crd['lng'])
    except:
        pass

len(lat)을 해서 보니 3개 정도 주소를 받지 못한 것 같다. 이러면 인덱스가 문제다. 어떤게 오류가 났는지 확인할 필요가 있어 보인다.  

 

lat = []
lng = []
for i in range(35):
    try:
        station_name = "부산 " + index[i]
        crd = geocoding(station_name)
        lat.append(crd['lat'])
        lng.append(crd['lng'])
    except Exception as e:
        print(station_name,e)
부산 부산북항 'NoneType' object has no attribute 'latitude'
부산 부산감만 'NoneType' object has no attribute 'latitude'
부산 대신동 'NoneType' object has no attribute 'latitude'

부산 부산북항, 감만, 대신동이 위도, 경도 변환이 안 된 것을 볼 수 가 있다. 이 부분을 제외를 하고 진행을 한다.

 

# Index 수정
remove_set = {'부산북항', '부산감만','대신동'}

rm_index = [i for i in index if i not in remove_set]
print(rm_index)
['광복동', '초량동', '태종대', '청학동', '전포동', '온천동', '명장동', '대연동', '용호동', '학장동', '덕천동', '화명동', '삼락동', '개금동', '당리동', '부산항', '부산신항', '청룡동', '좌동', '재송동', '장림동', '대저동', '녹산동', '명지동', '연산동', '기장읍', '용수리', '수정동', '부곡동', '회동동', '광안동', '덕포동']
### 전체 코드 ###

# Package
from geopy.geocoders import Nominatim
import folium

# 위도, 경도 변환
def geocoding(address):
    geolocoder = Nominatim(user_agent = 'South Korea', timeout=None)
    geo = geolocoder.geocode(address)
    crd = {"lat": str(geo.latitude), "lng": str(geo.longitude)}
	return crd
    
# 각 index에 대한 위도, 경도 가져오기, 없는 값은 제외
lat = []
lng = []
for i in range(35):
    try:
        station_name = "부산 " + index[i]
        crd = geocoding(station_name)
        lat.append(crd['lat'])
        lng.append(crd['lng'])
    except:
        pass

# 위치 중 변환 안된 Index 제외
remove_set = {'부산북항', '부산감만','대신동'}

rm_index = [i for i in index if i not in remove_set]
print(rm_index)

# 위치 표시
# 중심지점
busan_map = folium.Map(location=[35.1795543,129.0756416] zoom_start=18)
 
df_cities = pd.DataFrame({'위도': lat, '경도': lng}, 
    index = rm_index)
 
print(df_cities)
 
for i in range(len(df_cities)):
    folium.Marker([df_cities.iloc[i][0], df_cities.iloc[i][1]], popup=df_cities.index[i]).add_to(busan_map)
 
busan_map.save('busan_obs.html')
                      위도                 경도
광복동   35.100358850000006  129.0306070630278
초량동           35.1157823          129.04265
태종대          35.05850995  129.0876858033858
청학동             35.09106          129.06497
전포동           35.1572828        129.0745022
온천동           35.2158722          129.07023
명장동             35.20755          129.10356
대연동           35.1343823        129.0938404
용호동           35.1190255        129.1126529
학장동           35.1422194        128.9843177
덕천동           35.2122143        129.0115542
화명동           35.2326638         129.010709
삼락동           35.1837761        128.9791895
개금동           35.1527311        129.0213975
당리동           35.1071561        128.9768898
부산항           35.1050889        129.0639918
부산신항          35.1178873        128.8467054
청룡동             35.28324          129.07324
좌동            35.1781799        129.1759973
재송동           35.1858554         129.124651
장림동             35.07509          128.96829
대저동           35.1586386        128.9535924
녹산동           35.1116974         128.869001
명지동           35.1071356        128.9179423
연산동           35.1834421        129.0899339
기장읍           35.2385796        129.2158159
용수리             35.33662          129.17312
수정동           35.1305163        129.0413108
부곡동           35.2339453         129.093848
회동동             35.23105          129.12173
광안동           35.1590134         129.113064
덕포동           35.1754906        128.9854608

부산신항, 부산감만을 제외한 곳에서  녹산동이 제일 높았는데 산업단지 주변이라 그런것 같다. 미세먼지 프로젝트를 했을 때 한강 기준으로 동, 서 차이가 났는데 여기서는 좌동도 높게 나온것을 보면 딱히 그렇게 의미있는 결과였던 것은 아니였던 것 같다.

 

busan_obs.html
0.03MB

'Python > 학습용' 카테고리의 다른 글

20 뉴스그룹 분류  (0) 2023.03.28
텍스트 분석  (0) 2023.03.27
API(2)  (1) 2023.03.20
API(1)  (0) 2023.03.18
웹 스크랩핑(4)  (0) 2023.03.17