공공 데이터 csv 파일로 저장하기 [1]

센트럴리밋 2017.07.20 16:06

 국내의 공공 데이터 역시 시대의 흐름에 맞게 open API로,

 딥러닝을 포함한 여러 데이터 기반 어플리케이션 프로그램 제작에 필요한 데이터들이 open API 를 통해 공개 되어 있다.  (https://www.data.go.kr/)

 이 사이트에서 자신이 원하는 데이터의 종류를 검색하고, 매우 간단한 회원 가입을 통해 (즉, 공인인증서와 같은 번거롭고 복잡한 절차 없는 가입을 통해)

 서비스 키를 요청하면 대부분의 데이터의 경우 자동적이고 즉각적으로 api key가 발급이 된다.

 

이때 url로 쿼리를 전송하여 공공 데이터를 저장하는데 사용한 언어는 python인데 다른 경우들과 마찬가지로 한글 encoding이 꽤나 귀찮은 문제가 되곤한다.

따라서 이번 포스트에서는 한글을 포함한 공공 데이터 파일을 query를 통해 요청하고 그 response를 한글 encoding으로 저장하여, 

궁극적으로 이 데이터를 csv 로 저장하는 방법에 대해 다루도록 하겠다.

 

Part1 에서는 쿼리를 보내고, 이 쿼리의 데이터를 어레이로 저장하는 법에 대해 다루고,

Part2에서는 그 쿼리의 데이터를 csv로 저장하는 법에 대해 다루겠다.

 

1. Query sender 메소드: 

- 기능: local code( 서울 시내 특정 구에 해당하는 코드), time code(201612와 같이 특정 연월을 입력함.) 을 받아, 

특정 구에서 특정 연월에 일어난 아파트 실거래 데이터를 한글로 읽어들여 문자열로 저장하는 함수이다.

- 구현

이 때 url 코드로 쿼리를 전송하는데, 쿼리의 내용을 작성하고 요청을 전송하기 위해 request instance를 만들어야하는데 python3 의 경우 다음과 같은 library import가 필요하다.

 

import urllib.request

 

이 때 urllib.request.urlopen(request).read() 를 통해 쿼리를 전송하고 response를 읽어온다. 

그리고 이 response는 utf-8 format이 아닐 수 있기 때문에, response body를 "utf-8"  로 읽어들여 스트링으로 저장한다.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

 

def query_sender(localcode, timecode): url = 'http://openapi.molit.go.kr:8081/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTrade?' code_info = 'LAWD_CD='+ localcode + '&DEAL_YMD=' + timecode key = '&serviceKey=발급한 서비스키' request = urllib.request.Request(url+code_info+key) request.get_method = lambda: 'GET' response_body = urllib.request.urlopen(request).read() u = str(response_body, "utf-8") return u

 

- 사용: 그러면 아래와 같이 쿼리를 보내면, 쿼리에 대한 응답을 문자열로 반환한다.

s  = query_sender('11110','201612')

그러나 이는 문자열에 지나지 않으며, 우리가 원하는 정보들을 산발적으로 보관하고 있다.

 따라서 이 스트링으로 부터 우리가 원하는 정보를 csv형태로 저장하는 메소드가 추가적으로 더 필요하다.

 

2. Xml_to_item_list

- 기능:  xml_string과 local_name과 time code를 받아, xml string으로 부터 data array를 만든다.

- 구현:  

import xml.etree.ElementTree as ET
from xml.etree.ElementTree import parse, Element

먼저 xml string 스트링을 parsing하여, elementTree를 만든다. ( ElementTree는,  xml을 효율적으로 관리해 데이터를 tree형태로 보관할수 있도록 하는 python 외부 라이브러리이다.)

(없는 경우 pip3 install ElementTree를 통해 설치하도록 하자.) 이 경우 ET.fromstring(xml_string)는, 그 tree의 root를 반환하기 때문에 우리가 원하는 item list를 반환받기 위해서는

elements = root.findall('body/items/item')

과 같이 해주어야한다. 그리고 이 elements list를 순회하면서, item_list array에 정보들을 append하고, 이를 result에 append하면 된다.

 (그리고 중간에 에러가 날 수 있는데, 이 부분은 저장하지 않도록 한다. missing entry가 있는 record는 추후 에러를 일으킬 소지가 있다.)

def xml_to_item_list(xml_string,local_name, timecode):
    result = []
    root = ET.fromstring(xml_string)
    elements = root.findall('body/items/item')
    for item in elements:
        try:
            item_list = []
            item_list.append(time_code)
            item_list.append(item.find('거래금액').text)
            item_list.append(item.find('건축년도').text)
            item_list.append(local_name+" "+item.find('법정동').text+" "+item.find('지번').text)
            item_list.append(item.find('아파트').text)
            item_list.append(item.find('전용면적').text)
            result.append(item_list)
        except Exception as e:
            print("This row will be ignored. ",item_list)            
    return result 

- 사용 : 그리고  다음과 같이 이 함수를 호출하면, 해당 쿼리에 저장된 데이터들이 array에 마치맞게 잘 저장이 된다.

item_list = xml_to_item_list(xml_string,'11110','201612')

이를 pprint로 출력하면

[['201612', '    87,000', '2000', '11110  청운동 56-45', '청운현대', '129.76'],
 ['201612', '   114,500', '2008', '11110  사직동 9', '광화문풍림스페이스본(9-0)', '146.92'],
 ['201612', '   100,500', '2008', '11110  사직동 9', '광화문풍림스페이스본(9-0)', '131.44'],
 ['201612', '   117,500', '2004', '11110  내수동 72', '경희궁의아침3단지', '150.48'],
 ['201612', '    98,000', '2003', '11110  내수동 95', '파크팰리스', '117.26'],
 ['201612', '    96,000', '2003', '11110  내수동 95', '파크팰리스', '103.77'],
 ['201612', '   118,500', '2004', '11110  내수동 73', '경희궁의아침4단지', '124.17'],
 ['201612', '    92,000', '2003', '11110  내수동 95', '파크팰리스', '103.77'],
 ['201612', '   125,000', '2004', '11110  내수동 73', '경희궁의아침4단지', '150.77'],
 ['201612', '    28,000', '2003', '11110  익선동 55', '현대뜨레비앙', '48.54'],
 ['201612', '    27,000', '2003', '11110  익선동 55', '현대뜨레비앙', '48.54'],
 ['201612', '    39,000', '1998', '11110  익선동 30-6', '운현신화타워', '84.91'],
 ['201612', '    25,000', '2003', '11110  익선동 55', '현대뜨레비앙', '46.64'],
 ['201612', '    51,000', '2006', '11110  인의동 48-2', '효성쥬얼리시티', '98.39'],
 ['201612', '    63,000', '2006', '11110  인의동 48-2', '효성쥬얼리시티', '106.81'],
 ['201612', '    55,000', '2006', '11110  인의동 48-2', '효성쥬얼리시티', '84.7'],
 ['201612', '    17,700', '2014', '11110  연건동 195-10', '이화에수풀', '16.98'],
 ['201612', '    17,500', '2014', '11110  연건동 195-10', '이화에수풀', '16.98'],
 ['201612', '    18,000', '2014', '11110  연건동 195-10', '이화에수풀', '16.98'],
 ['201612', '    82,000', '1996', '11110  명륜2가 236', '아남2', '114.36'],
 ['201612', '    62,800', '1995', '11110  명륜2가 4', '아남1', '84.9'],
 ['201612', '    24,000', '1994', '11110  창신동 640-252', '성용', '59.28'],
 ['201612', '    31,000', '1993', '11110  창신동 703', '창신쌍용2', '64.66'],
 ['201612', '    37,500', '1993', '11110  창신동 703', '창신쌍용2', '79.87'],
 ['201612', '    31,600', '1993', '11110  창신동 703', '창신쌍용2', '54.7'],
 ['201612', '    45,100', '1993', '11110  창신동 703', '창신쌍용2', '106.62'],
 ['201612', '    42,200', '1999', '11110  창신동 232', '두산', '59.95'],
 ['201612', '    33,500', '1992', '11110  창신동 702', '창신쌍용1', '54.7'],
 ['201612', '    37,000', '1999', '11110  창신동 232', '두산', '59.95'],
 ['201612', '    11,300', '2013', '11110  숭인동 201-11', '종로유케이201', '12.01'],
 ['201612', '    14,200', '2013', '11110  숭인동 1421', '버넷하임1', '17.96'],
 ['201612', '    45,900', '2008', '11110  숭인동 2-1', '종로센트레빌', '59.92'],
 ['201612', '    13,900', '2012', '11110  숭인동 296-19', '삼전솔하임2차', '16.67'],
 ['201612', '    12,400', '2013', '11110  숭인동 1392-1', '종로아인스빌', '12.15'],
 ['201612', '    56,000', '2009', '11110  숭인동 766', '종로청계힐스테이트', '84.95'],
 ['201612', '    12,000', '2014', '11110  숭인동 1421-2', '숭인한양LEEPS', '12.78'],
 ['201612', '    45,800', '2008', '11110  숭인동 2-1', '종로센트레빌', '59.92'],
 ['201612', '    17,000', '1997', '11110  평창동 595', '갑을', '30.55'],
 ['201612', '    31,500', '1996', '11110  평창동 145-5', '일성빌라트', '59.82'],
 ['201612', '    72,000', '2008', '11110  평창동 102', '르트랑시망', '140.97'],
 ['201612', '   136,000', '2009', '11110  평창동 108', '롯데캐슬 로잔', '191.73'],
 ['201612', '    55,990', '2000', '11110  무악동 82', '현대', '84.92'],
 ['201612', '    48,000', '2000', '11110  무악동 82', '현대', '60'],
 ['201612', '    68,000', '2008', '11110  무악동 60', '인왕산아이파크', '84.86'],
 ['201612', '    74,000', '2008', '11110  무악동 60', '인왕산아이파크', '84.86'],
 ['201612', '    68,990', '2000', '11110  무악동 82', '현대', '114.9'],
 ['201612', '    63,990', '2000', '11110  무악동 82', '현대', '114.9'],
 ['201612', '    59,990', '2000', '11110  무악동 82', '현대', '84.92'],
 ['201612', '    59,490', '2000', '11110  무악동 82', '현대', '84.92'],
 ['201612', '    59,650', '2000', '11110  무악동 82', '현대', '84.92'],
 ['201612', '    85,900', '2008', '11110  무악동 60', '인왕산아이파크', '114.93']]

이 뜬다는 것을 알 수 있다.



출처: http://superelement.tistory.com/15 [아마추어 엔지니어 노트]

출처: http://superelement.tistory.com/15 [아마추어 엔지니어 노트]

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
24 [파이썬으로 구현한 알고리즘] (4) 버블 정렬(Bubble Sort) file 졸리운_곰 2018.02.27 679
23 [파이썬으로 구현한 알고리즘] (3) 선택 정렬(Selection Sort) file 졸리운_곰 2018.02.27 549
22 [파이썬으로 구현한 알고리즘] (2) 스택/큐 (Stack/Queue) file 졸리운_곰 2018.02.27 607
21 [파이썬으로 구현한 알고리즘] (1) 연결 리스트(Linked List) file 졸리운_곰 2018.02.27 946
20 텍스트 마이닝 4편. 형태소 분석(1/3) 졸리운_곰 2018.02.18 2013
19 텍스트 마이닝 3편. 형태소 분석 사전작업 졸리운_곰 2018.02.18 761
18 텍스트 마이닝 2편. 텍스트 파일 file 졸리운_곰 2018.02.18 1199
17 텍스트 마이닝 1편. 소개 file 졸리운_곰 2018.02.18 913
16 파이썬으로 MySQL DB에 데이터 저장하기, Python handles transactions with MySQL file 졸리운_곰 2018.02.14 469
15 공공 데이터 csv 파일로 저장하기 [3] 졸리운_곰 2017.10.10 663
14 공공 데이터 csv 파일로 저장하기 [2] 졸리운_곰 2017.10.10 559
» 공공 데이터 csv 파일로 저장하기 [1] 졸리운_곰 2017.10.10 517
12 JSON 데이타 가을의곰 2017.06.18 595
11 python으로 json 파일 쉽게 파싱하기 가을의곰 2017.06.18 779
10 Python에서 SQLAlchemy로 MS-SQL 연동하기 졸리운_곰 2017.05.07 439
9 python에서 sqlite 사용법 file 졸리운_곰 2017.04.26 876
8 Python의 pandas를 사용하면 몇줄의 코드만으로 Data Analysis를 쉽고 강력하게 처리할 수 있다 file 졸리운_곰 2017.03.05 648
7 파이썬으로 XML 처리하기 졸리운_곰 2016.11.15 388
6 SQLAlchemy 시작하기 졸리운_곰 2016.06.11 948
5 SQLAlchemy 시작하기 – Part 2 졸리운_곰 2016.06.11 539
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED