본문 바로가기

Python/Crawler

Python을 기반으로 정부 API를 사용하여 Json 파일 처리하기

API(json) with Python

대용량 데이터의 자료 관리 기술과 자료 분석 기술이 중요해지는 가운데 공공데이터포털과 같은 정부 사이트에서 공공기관이 생성 또는 취득하여 관리하고 있는 공공데이터를 제공하고 있다. 쉽고 편리하게 이용이 가능하도록 공공데이터를 파일데이터, 오픈 API, 시각화 등으로 제공하고 있으며 누구나 이용이 가능하며 영리 목적의 이용을 포함한 자유로운 활용이 보장된다.
이 위키에서는 데이터의 수월한 활용을 위하여 Python을 기반으로 오픈 API를 사용해보고 Json 데이터를 처리해본다.

1. Python 환경설정

Python 환경설정은 [해당 페이지](Python 환경설정)에 분류되어 있다.

2. 오픈 API

2.1 오픈 API란?

API는 Application Programming interface의 약자로 응용 프로그램 프로그래밍인터페이스를 말한다. 다양한 응용 프로그램에 사용할 수 있는 운영 체제, 혹은 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스이다.
오픈 API란 누구나 사용할 수 있도록 공개된 API를 말한다. 데이터를 표준화하고 프로그래밍해 외부 소프트웨어 개발자나 사용자들과 공유하는 프로그램이다. 개방된 오픈 API를 이용해 다양하고 재미있는 서비스나 애플리케이션, 다양한 형태의 플랫폼을 개발할 수 있다.

2.2 오픈 API 사용법

오픈 API를 사용하기 위해서는 인증키를 발급받아야 한다. 해당 사이트에 신청하여 알맞은 인증키를 발급받는다.

3. JSON

JSON(JavaScript Object Notation)은 '속성-값 쌍'(attribute-value pairs and array data types (or any other serializable value))또는 '키-값 쌍'으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다.
기본 자료형은 다음과 같다.

  • 문자열
  • 참/거짓(True/False)
  • 배열
  • 객체
  • null
  • JSON은 텍스트로 이루어져 있어 사람과 기계 모두 읽고 쓰기 쉬우며 서로 다른 시스템간에 객체를 교환하기 좋은 장점을 가지고 있다.

4. JSON 인코딩/디코딩

4.1 인코딩

Python Object(Dictionary, List, Tuple 등)을 JSON 문자열로 변경하는 것을 JSON Encoding라 부른다. Json 라이브러리를 import 한 이후 json.dumps() 를 사용하면 변환할 수 있다.

CODE

import json
#json 인코딩

#테스트용 Dicionary
item = {'id':1, 'name':'book', 'content' : [{'title':'Python for Beginner','contents':'Study Python'}]}

#JSON 인코딩
jsonString = json.dumps(item)

#출력
print(item)
print(type(item))
print(jsonString)
print(type(jsonString))

결과

{'id': 1, 'name': 'book', 'content': [{'title': 'Python for Beginner', 'contents': 'Study Python'}]}
<class 'dict'>
{"id": 1, "name": "book", "content": [{"title": "Python for Beginner", "contents": "Study Python"}]}
<class 'str'>

4.2 디코딩

인코딩과는 반대로 JSON 문자열을 Python 타입으로 변경하는 것을 JSON Decoding라고 부른다. json.loads() 메서드를 사용하여 문자열을 변경할 수 있다.

CODE

import json
#json 인코딩

#테스트용 Dicionary
jsonString = '{"id":1, "name":"book", "content" : [{"title":"Python for Beginner","contents":"Study Python"}]}'

#JSON 인코딩
item = json.loads(jsonString)
item = json.loads(jsonString)

#출력
print(jsonString)
print(type(jsonString))
print(item)
print(type(item))

결과

{"id":1, "name":"book", "content" : [{"title":"Python for Beginner","contents":"Study Python"}]}
<class 'str'>
{'id': 1, 'name': 'book', 'content': [{'title': 'Python for Beginner', 'contents': 'Study Python'}]}
<class 'dict'>

5. API 사용해보기

해당 포스팅에서는 식품의약품안전처 데이터활용서비스가 제공하고 있는 API를 사용하여 진행된다.

5.1 요청하기

API 인증키를 발급받은 후 사용하고 싶은 데이터베이스에 접근하여 요청 주소를 살펴본다. 식품의약품안전처 데이터 활용 서비스는 요청 주소가 다음과 같이 구성되어 있다.
http://openapi.foodsafetykorea.go.kr/api/keyId/serviceId/dataType/startIdx/endIdx

KeyID ServiceID DataType StartIdx EndIdx
본인 API Key 사용하고자 하는 DB XML/JSON 선택 시작 ROW 끝 ROW

가져오는 행의 개수는 천 개를 넘길 수 없으며 천 개 이상의 데이터가 필요할 경우 여러번 요청하여 가져와야 한다. 주소를 입력해 데이터를 살펴본다.

결과

{"I0750":{"RESULT":{"MSG":"정상처리되었습니다.","CODE":"INFO-000"},"total_count":"22721","row":[{"NUTR_CONT3":"10.1","NUTR_CONT2":"67.8","NUTR_CONT1":"349","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2001","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000100000001","NUTR_CONT7":"N/A","NUTR_CONT6":"N/A","NUTR_CONT5":"N/A","NUTR_CONT4":"3.7","DESC_KOR":"고량미,알곡","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"1","ANIMAL_PLANT":""},{"NUTR_CONT3":"11.4","NUTR_CONT2":"73.5","NUTR_CONT1":"373","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2011","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000200200001","NUTR_CONT7":"0","NUTR_CONT6":"2","NUTR_CONT5":"N/A","NUTR_CONT4":"3.7","DESC_KOR":"겉귀리,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"2","ANIMAL_PLANT":""},{"NUTR_CONT3":"11.4","NUTR_CONT2":"73.5","NUTR_CONT1":"332","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2017","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000200200001","NUTR_CONT7":"N/A","NUTR_CONT6":"2","NUTR_CONT5":"N/A","NUTR_CONT4":"3.7","DESC_KOR":"겉귀리,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"3","ANIMAL_PLANT":""},{"NUTR_CONT3":"14.3","NUTR_CONT2":"70.4","NUTR_CONT1":"371","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2011","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000200300001","NUTR_CONT7":"N/A","NUTR_CONT6":"3","NUTR_CONT5":"N/A","NUTR_CONT4":"3.8","DESC_KOR":"쌀귀리,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"4","ANIMAL_PLANT":""},{"NUTR_CONT3":"14.3","NUTR_CONT2":"70.4","NUTR_CONT1":"334","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2017","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000200300001","NUTR_CONT7":"N/A","NUTR_CONT6":"3","NUTR_CONT5":"N/A","NUTR_CONT4":"3.8","DESC_KOR":"쌀귀리,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"5","ANIMAL_PLANT":""},{"NUTR_CONT3":"13.2","NUTR_CONT2":"64.9","NUTR_CONT1":"382","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2011","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000300000001","NUTR_CONT7":"0","NUTR_CONT6":"4","NUTR_CONT5":"N/A","NUTR_CONT4":"8.2","DESC_KOR":"오트밀","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"6","ANIMAL_PLANT":""},{"NUTR_CONT3":"13.2","NUTR_CONT2":"64.9","NUTR_CONT1":"348","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2017","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000300000001","NUTR_CONT7":"N/A","NUTR_CONT6":"4","NUTR_CONT5":"N/A","NUTR_CONT4":"8.2","DESC_KOR":"오트밀","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"7","ANIMAL_PLANT":""},{"NUTR_CONT3":"11.2","NUTR_CONT2":"74.6","NUTR_CONT1":"367","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2011","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000400200001","NUTR_CONT7":"0","NUTR_CONT6":"6","NUTR_CONT5":"N/A","NUTR_CONT4":"1.9","DESC_KOR":"기장,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"8","ANIMAL_PLANT":""},{"NUTR_CONT3":"11.2","NUTR_CONT2":"74.6","NUTR_CONT1":"360","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2017","NUTR_CONT9":"N/A","NUTR_CONT8":"N/A","FOOD_CD":"100101000400200001","NUTR_CONT7":"N/A","NUTR_CONT6":"6","NUTR_CONT5":"N/A","NUTR_CONT4":"1.9","DESC_KOR":"기장,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"9","ANIMAL_PLANT":""},{"NUTR_CONT3":"11.5","NUTR_CONT2":"74.7","NUTR_CONT1":"374","FOOD_GROUP":"농촌진흥청  식품성분표 DB","BGN_YEAR":"2011","NUTR_CONT9":"N/A","NUTR_CONT8":"0.59","FOOD_CD":"100101000500100001","NUTR_CONT7":"0","NUTR_CONT6":"14","NUTR_CONT5":"N/A","NUTR_CONT4":"2.3","DESC_KOR":"메밀,생것","SERVING_WT":"100","FDGRP_NM":"곡류 및 그 제품","NUM":"10","ANIMAL_PLANT":""}]}}

1번째 열부터 10번째 열까지 요청하여 받은 모습이다.

5.2 JSON 디코딩

4.2에서 사용했던 방식으로 데이터를 디코딩해본다.

CODE

from __future__ import print_function
import json, urllib.request
#위키 작성을 위해 편집된 CODE
apikey = '개인 API KEY'
#개인이 지급 받는 api key

startRow = 1
endRow = 10
#원하는 row 선택을 위해 변수로 나누어줌

url = 'http://openapi.foodsafetykorea.go.kr/api/' + apikey + '/I0750/json/' + str(startRow) + '/' + str(endRow)

data = urllib.request.urlopen(url).read()
output = json.loads(data)

print(output)

결과

{'I0750': {'RESULT': {'MSG': '정상처리되었습니다.', 'CODE': 'INFO-000'}, 'total_count': '22721', 'row': [{'NUTR_CONT3': '10.1', 'NUTR_CONT2': '67.8', 'NUTR_CONT1': '349', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2001', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000100000001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': 'N/A', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.7', 'DESC_KOR': '고량미,알곡', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '1', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.4', 'NUTR_CONT2': '73.5', 'NUTR_CONT1': '373', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200200001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '2', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.7', 'DESC_KOR': '겉귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '2', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.4', 'NUTR_CONT2': '73.5', 'NUTR_CONT1': '332', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200200001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '2', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.7', 'DESC_KOR': '겉귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '3', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '14.3', 'NUTR_CONT2': '70.4', 'NUTR_CONT1': '371', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200300001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '3', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.8', 'DESC_KOR': '쌀귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '4', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '14.3', 'NUTR_CONT2': '70.4', 'NUTR_CONT1': '334', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200300001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '3', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.8', 'DESC_KOR': '쌀귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '5', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '13.2', 'NUTR_CONT2': '64.9', 'NUTR_CONT1': '382', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000300000001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '4', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '8.2', 'DESC_KOR': '오트밀', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '6', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '13.2', 'NUTR_CONT2': '64.9', 'NUTR_CONT1': '348', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000300000001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '4', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '8.2', 'DESC_KOR': '오트밀', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '7', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.2', 'NUTR_CONT2': '74.6', 'NUTR_CONT1': '367', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000400200001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '6', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '1.9', 'DESC_KOR': '기장,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '8', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.2', 'NUTR_CONT2': '74.6', 'NUTR_CONT1': '360', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000400200001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '6', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '1.9', 'DESC_KOR': '기장,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '9', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.5', 'NUTR_CONT2': '74.7', 'NUTR_CONT1': '374', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': '0.59', 'FOOD_CD': '100101000500100001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '14', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '2.3', 'DESC_KOR': '메밀,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '10', 'ANIMAL_PLANT': ''}]}}

5.3 CSV 파일로 출력해보기

JSON 파일의 형식은 사용하는 API마다 다르기 때문에 이 부분은 참고 용도로 사용해야 한다


데이터를 디코딩 한 결과의 타입을 보면 Dictionary인 것을 알 수 있다. 하지만 사용하고자 하는 데이터는 일반적인 Dictionary 타입과 다르다. 직접적으로 필요한 데이터인 'Row' 부분이 Key가 아닌 Value인 것을 확인할 수 있다. 이를 적절한 변환을 통해 Dictionary 타입으로 바꾸어준다.

타입 출력

print(type(output))
결과 : <class 'dict'>

결과와 타입을 참고하여 적절히 변환시킨다.

값을 사전으로 변환

output = json.loads(data)
output = output['I0750']
output = output['row']

변환 결과는 다음과 같다.

결과

[{'NUTR_CONT3': '10.1', 'NUTR_CONT2': '67.8', 'NUTR_CONT1': '349', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2001', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000100000001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': 'N/A', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.7', 'DESC_KOR': '고량미,알곡', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '1', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.4', 'NUTR_CONT2': '73.5', 'NUTR_CONT1': '373', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200200001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '2', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.7', 'DESC_KOR': '겉귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '2', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.4', 'NUTR_CONT2': '73.5', 'NUTR_CONT1': '332', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200200001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '2', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.7', 'DESC_KOR': '겉귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '3', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '14.3', 'NUTR_CONT2': '70.4', 'NUTR_CONT1': '371', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200300001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '3', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.8', 'DESC_KOR': '쌀귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '4', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '14.3', 'NUTR_CONT2': '70.4', 'NUTR_CONT1': '334', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000200300001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '3', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '3.8', 'DESC_KOR': '쌀귀리,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '5', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '13.2', 'NUTR_CONT2': '64.9', 'NUTR_CONT1': '382', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000300000001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '4', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '8.2', 'DESC_KOR': '오트밀', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '6', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '13.2', 'NUTR_CONT2': '64.9', 'NUTR_CONT1': '348', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000300000001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '4', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '8.2', 'DESC_KOR': '오트밀', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '7', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.2', 'NUTR_CONT2': '74.6', 'NUTR_CONT1': '367', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000400200001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '6', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '1.9', 'DESC_KOR': '기장,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '8', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.2', 'NUTR_CONT2': '74.6', 'NUTR_CONT1': '360', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2017', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': 'N/A', 'FOOD_CD': '100101000400200001', 'NUTR_CONT7': 'N/A', 'NUTR_CONT6': '6', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '1.9', 'DESC_KOR': '기장,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '9', 'ANIMAL_PLANT': ''}, {'NUTR_CONT3': '11.5', 'NUTR_CONT2': '74.7', 'NUTR_CONT1': '374', 'FOOD_GROUP': '농촌진흥청  식품성분표 DB', 'BGN_YEAR': '2011', 'NUTR_CONT9': 'N/A', 'NUTR_CONT8': '0.59', 'FOOD_CD': '100101000500100001', 'NUTR_CONT7': '0', 'NUTR_CONT6': '14', 'NUTR_CONT5': 'N/A', 'NUTR_CONT4': '2.3', 'DESC_KOR': '메밀,생것', 'SERVING_WT': '100', 'FDGRP_NM': '곡류 및 그 제품', 'NUM': '10', 'ANIMAL_PLANT': ''}]

변환결과는 [{Dict 1}, {Dict 2}, {Dict 3}, …] 의 리스트 형식인 것을 알 수 있다. 리스트의 원소가 원하는 데이터이므로 이 것을 그대로 저장해주면 된다. 편의를 위해 Dict 1의 Key 값을 Column 명으로 저장해준다.

#output[0]은 output_columns와 같다
# output_columns = ['NUM','FOOD_CD','FDGRP_NM','DESC_KOR','SERVING_WT',
#'NUTR_CONT1','NUTR_CONT2','NUTR_CONT3','NUTR_CONT4','NUTR_CONT5','NUTR_CONT6','NUTR_CONT7','NUTR_CONT8','NUTR_CONT9', 'ANIMAL_PLANT','BGN_YEAR','FOOD_GROUP']

try :
    with open(output_file, 'w', newline='', encoding='UTF-8') as csvfile :
        writer = csv.DictWriter(csvfile, output[0].keys())
        writer.writeheader()
        for data in output:
            writer.writerow(data)
except :
    print("Error")

실행 이후 CSV 파일이 저장 된 것을 확인한다.

5.4 전체 코드

API 사용을 위해 작성된 전체 코드

import json, urllib.request
import csv

apikey = 'API KEY'
#개인이 지급 받는 api key

startRow = 1
endRow = 10
#원하는 row 선택을 위해 변수로 나누어줌

url = 'http://openapi.foodsafetykorea.go.kr/api/' + apikey + '/I0750/json/' + str(startRow) + '/' + str(endRow)

data = urllib.request.urlopen(url).read()
output = json.loads(data)
output = output['I0750']
output = output['row']
print(output)
# print(type(output))

print(output[0].keys())
output_file = 'api_Output.csv'

# output_columns = ['NUM','FOOD_CD','FDGRP_NM','DESC_KOR','SERVING_WT',
# 'NUTR_CONT1','NUTR_CONT2','NUTR_CONT3','NUTR_CONT4','NUTR_CONT5','NUTR_CONT6','NUTR_CONT7','NUTR_CONT8','NUTR_CONT9',
# 'ANIMAL_PLANT','BGN_YEAR','FOOD_GROUP']

try :
    with open(output_file, 'w', newline='', encoding='UTF-8') as csvfile :
        writer = csv.DictWriter(csvfile, output[0].keys())
        writer.writeheader()
        for data in output:
            writer.writerow(data)
except :
    print("Error")