대기오염 정보 파싱하기

대기오염 정보를 가져다가 파싱해보자. 대기오염 실시간 예보 사이트인 airkorea에서 우리동네 예보 페이지를 뜯어보니 아래와 같은 주소로 데이터를 json으로 받아오고 있었다.

http://www.airkorea.or.kr/web/pollution/getRealChart
?dateDiv=1
&period=1
&stationCode=823652

여기서 stationCode는 관측소 코드가 된다. 집에서 그나마 가까운 검단 관측소의 코드는 823652였다.

이제 데이터 모양을 보자. 차트 작성을 위해 시계열 데이터를 받아오는데, 각 단위 데이터의 필드 키는 다음과 같은 의미를 갖는 것으로 보인다.

{
    "charts": [{
        "I10003_GRADE": "1", // 오존 등급
        "I10002_GRADE": "1", // 일산화 탄소 등급
        "KHAI_GRADE": "4", // 통합 대기 환경 등급
        "PERIOD": "1", // 시간?
        "KHAI_VALUE": "303", // 통합 대기 환경 지수
        "I10006_GRADE": "3", // 이산화 질소
        "I10001_GRADE": "1", // 아황산 가스 
        "VALUE_10007": "223", // 미세먼지(PM10) 농도값 
        "VALUE_24AVG_10008": null, // PM2.5의 24시간 평균
        "VALUE_10008": null,  // PM2.5의 농도값
        "VALUE_10006": "0.080", // 이산화질소 ppm
        "VALUE_24AVG_10007": "154", // PM10 미세먼지 평균
        "DATADIV": "1", // 단위?
        "DATA_TIME": "03-17:12", // 측정일시 
        "I10008_GRADE": null, // PM2.5 등급 
        "VALUE_10003": "0.014", // 오존 농도값
        "I10007_GRADE": "4", // 미세먼지 등급
        "VALUE_10001": "0.017", // 아황산 가스 농도 
        "DATA_TIME_CHART": "2015/03/17 11:00",
        "VALUE_10002": "1.1", // 일산화탄소 
        "KHAI_ITEM_CODE": "10007" // 주요오염물질 코드 
    }, 
    ....
    ]

11시에 이미 223을 찍고 있다….

다른 데이터로는 시도별 데이터를 볼 수 있는 팝업이 있다.

다음은 실시간 자료 중에서 최근 값을 가져와서 출력해주는 코드

from urllib.request import Request, urlopen
import json

URL = "http://www.airkorea.or.kr/web/pollution/getRealChart?dateDiv=1&period=1&stationCode=823652"

request = Request(URL)
res = urlopen(request)
raw_data = res.read().decode('utf-8')
data = json.loads(raw_data)

serial_data = sorted(data['charts'], key=lambda x:x['DATA_TIME_CHART'], reverse=True);
p = serial_data[0]

"""
미세먼지 코드 : 100007
"""

print("""최종측정: {DATA_TIME_CHART}
대기오염등급: {KHAI_GRADE}
미세먼지등급: {I10007_GRADE}
미세먼지농도: {VALUE_10007}""".format(**p))

그 외에 시도별로 미세먼지 지수만 따로 보여주는 페이지가 있는데, 이 페이지를 파싱해서 데이터를 뽑아보자. 이번에는 그냥 HTML 테이블로 바로 내려오는 데이터이기 때문에 BeautifulSoup을 이용해서 파싱하고 그 중에서 찾고자 하는 지역의 내용만 추려서 보여준다.

from datetime import datetime
from urllib.request import urlopen
from bs4 import BeautifulSoup

def get_raw_data():
    now = datetime.now()
    today_str = "{:04d}-{:02d}-{:02d}".format(now.year, now.month, now.day)
    g_URL = "http://www.airkorea.or.kr/sido_compare_p01?itemCode=10007&ymd={}%2023&areaCode=031".format(today_str)
    html_str = urlopen(g_URL).read().decode('utf-8')
    return html_str

def get_data_where(location_):
    html = get_raw_data()
    soup = BeautifulSoup(html)
    trs = [tr for tr in soup.find_all('tr') if location_ in tr.text]
    if trs:
        data = [x for x in trs[0].text.strip().split('n')]
        data[1:] = [int(x) for x in data[1:] if x != '-']
        return data
    return None

def print_data_where(location_):
    data = get_data_where(location_)
    for i, d in enumerate(data[1:]):
        print("{}시: {}".format(i+1, d))


print_data_where("통진")