Last active
March 28, 2019 08:33
-
-
Save 2minchul/a8cabbc8e86bb14c9f7e38859fca4f14 to your computer and use it in GitHub Desktop.
Scraping data from: http://www.weather.go.kr/weather/climate/past_cal.jsp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # coding=utf-8 | |
| import re | |
| import requests | |
| from bs4 import BeautifulSoup, Tag | |
| weather_pattern = re.compile( | |
| r'''(?P<name>[^<>]+?) # name group | |
| \s*?:\s*? # split by ':' | |
| (?P<value> # value group | |
| (?: | |
| [-+]? # optional: '-' or '+' | |
| (?:\d*[.]\d+)|(?:\d+[.]?) # (.d or d.d) or (d. or d) | |
| ) | - # or just '-' | |
| )''', | |
| re.VERBOSE # 정규표현식에 주석을 허용하고 공백은 무시 | |
| ) | |
| stn_table = {'서울': '108', '백령도': '102', '동두천': '98', '파주': '99', '인천': '112', '수원': '119', | |
| '강화': '201', '양평': '202', '이천': '203', '북춘천': '93', '철원': '95', '춘천': '101', | |
| '원주': '114', '영월': '121', '인제': '211', '홍천': '212', '북강릉': '104', '울릉도': '115', | |
| '강릉': '105', '속초': '90', '대관령': '100', '동해': '106', '태백': '216', '정선군': '217', | |
| '청주': '131', '충주': '127', '추풍령': '135', '제천': '221', '보은': '226', '홍성': '177', | |
| '대전': '133', '서산': '129', '천안': '232', '보령': '235', '부여': '236', '금산': '238', | |
| '전주': '146', '군산': '140', '부안': '243', '임실': '244', '정읍': '245', '남원': '247', | |
| '장수': '248', '순창': '254', '고창': '172', '고창(구)': '251', '광주': '156', '목포': '165', | |
| '흑산도': '169', '여수': '168', '완도': '170', '진도(첨찰산)': '175', '진도군': '268', '영광': '252', | |
| '순천': '174', '순천(구)': '256', '장흥': '260', '해남': '261', '고흥': '262', '강진군': '259', | |
| '보성군': '258', '광양': '266', '안동': '136', '포항': '138', '대구': '143', '대구(구)': '176', | |
| '울진': '130', '상주': '137', '봉화': '271', '영주': '272', '문경': '273', '영덕': '277', | |
| '의성': '278', '구미': '279', '영천': '281', '청송군': '276', '경주': '283', '부산': '159', | |
| '울산': '152', '창원': '155', '북창원': '255', '통영': '162', '진주': '192', '거창': '284', | |
| '합천': '285', '밀양': '288', '산청': '289', '거제': '294', '남해': '295', '김해시': '253', | |
| '양산': '257', '의령군': '263', '함양군': '264', '제주': '184', '고산': '185', '서귀포': '189', | |
| '성산': '188'} | |
| def get_weather(local, year, month, raise_if_failure=False): | |
| stn_code = local if local.isdigit() else stn_table.get(local) | |
| if not stn_code: # 없는 stn 코드 | |
| return | |
| response = requests.get( | |
| 'http://www.weather.go.kr/weather/climate/past_cal.jsp', | |
| params={'stn': stn_code, 'yy': str(year), 'mm': str(month), 'obs': '1'} | |
| ) | |
| if raise_if_failure: | |
| response.raise_for_status() | |
| return response.text | |
| def parse_weather(html): | |
| if not html: | |
| return | |
| soup = BeautifulSoup(html, 'html.parser') | |
| table = soup.find('table', {'class': 'table_develop'}) # type: Tag | |
| tr_object = iter(table.find_all('tr')) | |
| week_list = [] | |
| for th_ in next(tr_object).find_all('th'): # type: Tag | |
| week_list.append(th_.text.strip()) | |
| def th_generator(): | |
| while True: | |
| try: | |
| yield next(tr_object).find_all('td'), next(tr_object).find_all('td') | |
| except StopIteration: | |
| break | |
| for day_td_list, weather_td_list in th_generator(): | |
| for day_tr, weather_tr, week in zip(day_td_list, weather_td_list, week_list): # type: (Tag, Tag, str) | |
| day = day_tr.text.strip() | |
| if day: | |
| yield week, day, {rex.group('name'): rex.group('value') for rex in | |
| weather_pattern.finditer(str(weather_tr))} | |
| if __name__ == '__main__': | |
| print('서울') | |
| html = get_weather('서울', 2019, 3) | |
| for week, day, data in parse_weather(html): | |
| print(week, day, data) | |
| print('대전') | |
| html = get_weather('대전', 2018, 2) | |
| for week, day, data in parse_weather(html): | |
| print(week, day, data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment