본문 바로가기

Python/Crawler

PYTHON 크롤링을 이용한 수산식품 분석하기 - 2

검색 결과에 따른 데이터 수집 진행에 앞서 API 사용 방법에 대해 포스팅하고 넘어간다.

사용할 API는

https://www.foodsafetykorea.go.kr/apiMain.do

식품안전나라에서 제공하는 식품영양성분DB이다.

API키는 개인이 발급받으면 되고, API 형식은 다음과 같다.

http://openapi.foodsafetykorea.go.kr/api/keyId/serviceId/dataType/startIdx/endIdx

KeyId

ServiceID

dataType

startIdx

endIdx

본인 API Key

사용하고자하는 DB

XML/JSON 선택

시작 ROW

끝 ROW

시작 ROW와 끝 ROW는 천 개를 넘길 수 없다.

따라서 5천개를 가져오려면

1~1000

1001~2000

2001~3000

3001~4000

4001~5000

이런식으로 5번 가져와야 한다.

파이썬으로 간단하게 작성해보았다.

url = 'http://openapi.foodsafetykorea.go.kr/api/' + apikey + '/I0750/json/' + str(startRow) + '/' + str(endRow) data = urllib.request.urlopen(url).read() output = json.loads(data)

먼저 url을 json data에 넣어준다.

ingredientDDF = pd.DataFrame() ingredientDDF = ingredientDDF.append( {"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":""}, ignore_index = True)

이후 panda에 넣어준다.

제공되는 컬럼명을 입력하여 틀을 잡아준다.

total = output["I0750"]["total_count"] num = len(output["I0750"]["row"])

나의 경우 데이터의 전체가 필요했기 때문에 total을 잡아주었다.

JSON 파일 첫 부분에 보면 존재하는 것을 알 수 있다.

그리고 몇 개를 가져올 것인지 row를 통해 알려준다.

for i in range(0,num): ingredientDDF.ix[i,"NUTR_CONT3"] = output["I0750"]["row"][i]["NUTR_CONT3"] ingredientDDF.ix[i,"NUTR_CONT2"] = output["I0750"]["row"][i]["NUTR_CONT2"] ingredientDDF.ix[i,"NUTR_CONT1"] = output["I0750"]["row"][i]["NUTR_CONT1"] ingredientDDF.ix[i,"FOOD_GROUP"] = output["I0750"]["row"][i]["FOOD_GROUP"] ingredientDDF.ix[i,"NUTR_CONT9"] = output["I0750"]["row"][i]["NUTR_CONT9"] ingredientDDF.ix[i,"NUTR_CONT8"] = output["I0750"]["row"][i]["NUTR_CONT8"] ingredientDDF.ix[i,"FOOD_CD"] = output["I0750"]["row"][i]["FOOD_CD"] ingredientDDF.ix[i,"NUTR_CONT7"] = output["I0750"]["row"][i]["NUTR_CONT7"] ingredientDDF.ix[i,"NUTR_CONT6"] = output["I0750"]["row"][i]["NUTR_CONT6"] ingredientDDF.ix[i,"NUTR_CONT5"] = output["I0750"]["row"][i]["NUTR_CONT5"] ingredientDDF.ix[i,"NUTR_CONT4"] = output["I0750"]["row"][i]["NUTR_CONT4"] ingredientDDF.ix[i,"DESC_KOR"] = output["I0750"]["row"][i]["DESC_KOR"] ingredientDDF.ix[i,"SERVING_WT"] = output["I0750"]["row"][i]["SERVING_WT"] ingredientDDF.ix[i,"FDGRP_NM"] = output["I0750"]["row"][i]["FDGRP_NM"] ingredientDDF.ix[i,"NUM"] = output["I0750"]["row"][i]["NUM"] ingredientDDF.ix[i,"ANIMAL_PLANT"] = output["I0750"]["row"][i]["ANIMAL_PLANT"] ingredientDDF.to_csv("filename.csv", header=True, index=False, encoding='utf-8')

복잡하게 느껴지지만 N/A 값이 있기 때문에 일일히 지정해서 넣어준다.

이후 utf-8로 인코딩하여 csv 파일로 저장해준다.

이 방식을 여러번 반복하면 하나의 시트가 만들어진다.

처음에만 header를 주고 다음부터는 주지 않는 것이 좋다.

확인해보니 데이터 몇 건을 주기로 컬럼명이 조금씩 변형되기 때문이다.

ingredientDDF.to_csv("filename.csv", mode='a', header=False, index=False, encoding='utf-8') time.sleep(60)

그래서 이와같이 수정해서 넣어주었다.

그리고 api 홈페이지가 무진장 느리기 때문에 sleep를 적당히 주어 데이터를 가져올 수 있게 해주었다.

가져온 데이터는 csv로 저장되기 때문에 SQL Loader를 통해 넣어주면된다.

하지만 자동화 된 시스템을 원했기 때문에 난 Loader 대신 직접 Oracle DB에 넣는 방식을 택했다.

connection = cx_Oracle.connect('user/pwd@SERVER:1521/DATABASE')

Pyton과 Oracle은 cx_Oracle을 통해 연결된다.

연결 방법은 어렵지 않으니 패스하도록 하겠다.

먼저 커넥션을 통해 둘을 연결하여준다.

cursor = connection.cursor() L = []

이후 제어할 커서와 데이터를 담을 리스트를 만들어준다.

with open('filename.csv','rt', encoding='UTF8') as f: reader = csv.reader(f, delimiter=',') column_list='' value_list='' first_row=next(reader) column_string=','.join(first_row).translate('"') insert_string='insert into TABLE' + '(' +column_string+ ') values (' val_list = [] for i in range(1,len(first_row)+1): val_list.append(':'+str(i)) value_string=','.join(val_list) insert_string += value_string + ')' for row in reader: for index,col in enumerate(row): col_tr=col if col_tr: if col_tr[0] != '"': try: col_tr=datetime.datetime.strptime(col_tr,'%d-%b-%y') except ValueError: continue row[index] = col_tr L.append(row) print(insert_string) cursor.prepare(insert_string) cursor.executemany(None, L) connection.commit() cursor.close() connection.close()

CSV 파일을 열어주고 column_string과 insert_string(value)를 따로 만들어 주어 각각 합쳐준다.

python 실력이 좋지 않아 구글링해서 참고했는데 제대로 들어가는 것을 확인할 수 있었다.

참고로 로더보다 조금 느리다.

이렇게 진행하고 나면 API 데이터를 csv 파일로 저장하고 데이터베이스에 삽입까지 되는 것을 확인할 수 있다.

이제 비정형 데이터의 수집단계로 넘어간다.