2023.08.01 - [분류 전체보기] - 파이썬 OPEN API 가져오기
파이썬 OPEN API 가져오기
새로운 레시피를 추가하기 위해 식품의약품안전처에서 제공하는 공공데이터를 가져와야 한다. 1. 개인 KEY 받아오기 import json import requests API_KEY = '개인 KEY를 받아옴' URL = 'http://openapi.foodsafetykorea.
bpeach.tistory.com
위에서 가져온 OPEN API에서 RCP_PARTS_DTLS 부분 재료와 양 부분하여 정리하려고 한다.
1. 데이터 프레임을 딕셔너리로 변경
# 딕셔너리로 변경
data_dict = data.to_dict('records')
data_dict[:3]
위에 결과물을 보면 RCP_PARTS_DTLS 부분에 해당하는 것들이 정리 되지 않고 다양한 형태로 나와있다. 이부분을 먼저 정리하기 위해 정규 표현식를 사용하려고 한다.
2. 정규 표현식을 사용하고 튜플로 추출
# 재료(양g), ... 이런 식으로 된 거 분류
def extract_ingredients(recipe):
parts = recipe['RCP_PARTS_DTLS']
# 정규 표현식을 사용하여 재료와 양 튜플로 추출
# ([\w\s]+) : 재료 이름 그룹(알파벳과 숫자, 공백, + 패턴 한 번 이상 반복)
# \( : 괄호
# ([\d\.]+[k]? : 재료 양 그룹(숫자.소숫점, k분자가 있을 경우 고려_kg)
# g)\) : 'g' 다음 괄호 )
ingredients = re.findall(r'([\w\s]+)\(([\d\.]+[k]?g)\)', str(parts))
# 재료 이름 - 튜플의 첫번째요소(재료)에서 앞 뒤 공백 제거
ingredient_names = [ingredient[0].strip() for ingredient in ingredients]
# 재료 양 - 튜플의 두번째요소 양 저장
ingredient_amount = [ingredient[1] for ingredient in ingredients]
return ingredient_names, ingredient_amount
이 함수는 재료 중에서 재료명(양g) 형태로 저장된 것을 재료명과 양 따로 저장하기 위해 구현된 함수이다.
- finadall(pattern, text) : 은 문자열 내에 특정 패턴을 만족하는 모든 문자열 반환
- \w : 알파벳(문자) 또는 숫자
- \s : 공백
- + : 패턴 한 번 이상 반복
- \( : 괄호
- \d\. : 숫자. (소수)
- k? : 'k' 있을 경우 k 출력
- g)\ : 'g' 다음 괄호
튜플로 저장된 ingredients를 반복 읽어서 앞 뒤 공백 제거한 ingredient[0]을 재료명에 저장
3. 정리된 레시피 제목과 정보 추출해서 받아온거 데이터 목록에 추가
def get_recipe_data(recipe_name, data_dict):
for recipe in data_dict:
if recipe['RCP_NM'] == recipe_name:
ingredient_names, ingredient_amount = extract_ingredients(recipe)
# 딕셔너리로 구성하여 정리된 데이터 목록에 추가
recipe_data = {
'menu': recipe['RCP_NM'],
'rcp': ingredient_names,
'amount': ingredient_amount,
'eng': recipe['INFO_ENG'],
'car': recipe['INFO_CAR'],
'pro': recipe['INFO_PRO'],
'fat': recipe['INFO_FAT']
}
return recipe_data
# 정규 표현식으로 한 거 중에 없으면 None
return None
레시피명과 data 딕셔너리 정보를 받아와 RCP_NM와 레시피명이 같으면 위 언급한 함수에서 반환된 재료명과 재료양을 저장한다. 데이터를 딕셔너리로 구성하여 정리된 데이터 목록에 추가
food_name = []
result = []
# 제목만 추출
for i in data_dict:
name = i.get('RCP_NM')
food_name.append(name)
for recipe_name in food_name :
# 정리된 레시피 제목과 정보 추출
result_data = get_recipe_data(recipe_name, data_dict)
result.append(result_data)
print(result[:3])
4. 정규 표현식 사용
cleaned_data = []
for item in data_dict:
parts_details = item['RCP_PARTS_DTLS']
dish_name = item['RCP_NM']
# 정규 표현식을 사용하여 재료와 양 추출
# \b\w+ : 단어 앞뒤 지정으로 단어 의미
# \b\s\d+ : 단어앞뒤 지정하고 공백과 한 개 이상 숫자
# g(?:\(\d/\d\))? : g 포함해서 숫자/숫자와 형식 가능
ingredients_info = re.findall(r'\b\w+\b\s\d+g(?:\(\d/\d\))?', str(parts_details))
ingredient_name_list = []
amount_list = []
#print(ingredients_info)
# 재료와 양 추출해서 재료와 양 리스트에 넣기
for ingredient_info in ingredients_info:
# 단어 앞뒤+ 경계
ingredient_name, amount = re.findall(r'\b\w+\b', ingredient_info)[:2]
ingredient_name_list.append(ingredient_name+ ' ')
amount_list.append(amount+ ' ')
#print(ingredient_info)
# 영양 정보 추출
eng_info = item['INFO_ENG']
car_info = item['INFO_CAR']
pro_info = item['INFO_PRO']
fat_info = item['INFO_FAT']
# 딕셔너리로 구성하여 정리된 데이터 목록에 추가
dish_dict = {
'menu': dish_name,
'rcp': ingredient_name_list,
'amount' : amount_list,
'eng': eng_info,
'car': car_info,
'pro': pro_info,
'fat': fat_info
}
cleaned_data.append(dish_dict)
칵테일새우 20g(5마리) 처럼 저장된 데이터들을 분류하기 위해 정규 표현식 사용!
5. 나온 딕셔너리 결과 2개 합치기
total_data = cleanded_data + result
total_data[:3]
6. [] 빈칸으로 나온 데이터 채우기
merged_data = {}
for num in total_data :
menu_name = num['menu']
# menu_name에 merged_data의 키가 존재하지 않으면
if menu_name not in merged_data:
# merged 데이터 추가
merged_data[menu_name] = {'menu' : menu_name, 'rcp' : [], 'amount' : [], 'eng' : num['eng'], 'car' : num['car'], 'pro' : num['pro'], 'fat' : num['fat']}
# 키가 존재하면 리스트에 재료, 양 추가
merged_data[menu_name]['rcp'].extend(num['rcp'])
merged_dtat[menu_name]['amount'].extend(num['amount']
# 앞에 '재료'라는 단어가 들어가 있으면 제거
merged_data[menu_name]['rcp'] = [item.replace('재료 ', '') for item in merged_data[menu_name]['rcp']]
# merged_data에 저장된 값만 추출
merged_list = list(merged_data.values())
7. 재료명에서 끝에 오는 해당 단어를 가지고 카테고리별 분류
for item in data_dict:
menu_name = item['menu'].strip() # 공백 제거
last_word = menu_name.split()[-1] # 단어 하나씩 구분해서 마지막 문자만
if last_word.endswith('찜'): #찜으로 끝나는지
item['category'] = '찜류'
elif last_word == '소박이':
item['category'] = '김치류'
elif last_word.endswith('국') :
item['category'] = '국 및 탕류'
elif last_word.endswith('탕') :
item['category'] = '국 및 탕류'
elif last_word.endswith('찌개') :
item['category'] = '찌개 및 전골류'
elif last_word.endswith('전골') :
item['category'] = '찌개 및 전골류'
elif last_word.endswith('밥'):
item['category'] = '밥류'
elif last_word.endswith('샐러드'):
item['category'] = '샐러드'
elif last_word.endswith('죽'):
item['category'] = '죽'
# 메인메뉴에 돼지, 소고기, 닭, 오리가 있는지 확인하고 있으면 any() 에서 True 반환
elif any(word in menu_name
for word in ['돼지', '소고기', '닭', '오리']):
item['category'] = '메인메뉴'
else :
item['category'] = '서브메뉴3'
print(data_dict[:5])
8. 리스트 형태로 출력된 값에서 [] 제거, 'g'도 제거
rcp_remove = result['rcp'].str.replace(pat = r'[^\w,]', repl=r'', regex=True)
g_remove = result['amount'].str.replace(pat = r'[^\w,]', repl=r'', regex=True)
result['rcp'] = rcp_remove
result['remove_g'] = g_remove
result['amount'] = result['remove_g'].str.replace('g', '')
result[['menu', 'rcp', 'amount', 'eng', 'car', 'pro', 'fat', 'category']].head()
rcp에서 [] 제거 ^는 반대를 뜻한다.
- pat : 찾고자 하는 정규 표현식
- repl : 대체할 문자 입력
- regex : 정규표현식인지 결정 True : 정규화, False : 문자열
'Project > 23.07~08 AI' 카테고리의 다른 글
인공지능은?? (0) | 2023.08.01 |
---|---|
파이썬 OPEN API 가져오기 (0) | 2023.08.01 |
Pandas 활용하여 엑셀에서 첫 열 기준으로 정리하기 (0) | 2023.07.28 |
머신러닝_5. 단순회귀분석_규제 (0) | 2023.07.11 |
머신러닝_4. 모델링 (0) | 2023.07.11 |