본문 바로가기

코드이야기/Python

Beautiful Soup 라이브러리로 기온데이터 수집하기


작년 한 해 서울의 기온은 어떻게 변했을까요? 이런 작업을 하려면 날씨정보가 어디있는지 알아야 하고, 그 정보를 활용해서 우리가 보고싶은 모습으로 표현할 수 있어야 합니다. Weather Underground에서는 전세계의 날씨 데이터를 일자별, 주별, 월별, 기간별로 제공하고 있습니다.





한 가지 문제가 있습니다. 우리가 원하는 것은 일별 데이터인데 모두 확인하려면 대단한 노가다(?)를 해야한다는 것입니다. 파이썬의 Beautiful Soup 라이브러리를 활용하면 이 작업을 쉽게 처리할 수 있습니다. Beautiful Soup라이브러리는 html과 xml로 부터 데이터를 뽑아내기 위한 라이브러리 입니다. Beautiful Soup Document를 보시면 자세한 내용을 확인 할 수 있습니다.


이 라이브러리를 활용해서 서울의 기온데이터를 뽑아보도록 하겠습니다. 코드는 네이선 야우의 Visualize This를 참고하였습니다. 원래 파이썬 2로 작성된 것을 파이썬 3에서 평균기온, 최고기온, 최저기온을 추가로 표시할 수 있도록 수정한 것입니다.

#!-#-coding: utf8-*-

import urllib.request
from bs4 import BeautifulSoup

# 기온데이터를 저장할 파일을 쓰기모드로 연다
f = open('wunder-data-seoul.txt', 'w')

# 1월에서 12월까지 각 날짜의 페이지를 순회하면서 기온정보를 뽑아낸다
for m in range(1, 13):
    for d in range(1, 32):
        if (m == 2 and d > 28):   #2월이 28일을 넘으면 중단하고 다음 달로 넘어간다
            break
        elif (m in [4, 6, 9, 11] and d > 30):  #4, 6, 9, 11월이 30일을 넘으면 중단하고 다음 달로 넘어간다
            break
        
        if (len(str(m)) == 1) and (len(str(d)) == 1):
            timestamp = '20130' + str(m) + '0' + str(d)
        elif (len(str(m)) == 1) and (len(str(d)) == 2):
            timestamp = '20130' + str(m) + str(d)
        elif (len(str(m)) == 2) and (len(str(d)) == 1):
            timestamp = '2013' + str(m) + '0' + str(d)
        else:
            timestamp = '2013' + str(m) + str(d)
            
       	# 뽑아내려는 기온데이터가 들어있는 페이지를 urllib 라이브러리로 불러온다
        url = "http://english.wunderground.com/history/airport/RKSS/2013/" \
				+ str(m) + "/" + str(d) + \
				"/DailyHistory.html?req_city=NA&req_state=NA&req_statename=NA"
        page = urllib.request.urlopen(url)
        
	# Beautiful Soup 라이브러리로 기온데이터를 추출한다. 
	# 기온데이터는 nobr 클래스에 span태그로 둘러싸여 있다.
        soup = BeautifulSoup(page)
        dayMeanTemp = soup.find_all('span', attrs={"class":"nobr"})[0].span.string
        dayMaxTemp = soup.find_all('span', attrs={"class":"nobr"})[1].span.string
        dayMinTemp = soup.find_all('span', attrs={"class":"nobr"})[4].span.string

        print('date: {0},{1},{2},{3}'.format(timestamp, dayMeanTemp, dayMaxTemp, dayMinTemp))
        
        if len(str(m)) < 2:
            mStamp = '0' + str(m)
        else:
            mStamp = str(m)
            
        if len(str(d)) < 2:
            dStamp = '0' + str(d)
        else:
            dStamp = str(d)
        
        timestamp = '2013' + mStamp + dStamp
        
	#읽어온 기온데이터를 파일에 쓴다
	f.write(timestamp + ',' + dayMeanTemp + ',' + dayMaxTemp + ',' + dayMinTemp + '\n')

# 모든 데이터를 읽었으면, 기온데이터를 저장한 파일을 닫는다
f.close()

이제 서울의 2013년 기온데이터 365개를 일자별로 얻었습니다. 세부 데이터는 첨부파일을 참고하세요


get-weather-data-seoul.txt



Beautiful Soup라이브러리의 HTML, XML 파싱이 필요한 어디에서는 사용할 수 있습니다. 즐겁게 사용해 보시기 바랍니다.