File size: 3,762 Bytes
89b8989
 
 
 
 
 
 
 
 
 
 
 
 
 
a608ddf
89b8989
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# backend/app/services/nutrition_api_service.py
import os
import requests
from dotenv import load_dotenv
import logging

# 設置日誌
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 載入環境變數
load_dotenv()

# 從環境變數中獲取 API 金鑰
USDA_API_KEY = os.getenv("USDA_API_KEY", "4guYMPsU2jSnN6GH6NjexZmSh1VWrgmOIoH6d6ju")
USDA_API_URL = "https://api.nal.usda.gov/fdc/v1/foods/search"

# 我們關心的主要營養素及其在 USDA API 中的名稱或編號
# 我們可以透過 nutrient.nutrientNumber 或 nutrient.name 來匹配
NUTRIENT_MAP = {
    'calories': 'Energy',
    'protein': 'Protein',
    'fat': 'Total lipid (fat)',
    'carbs': 'Carbohydrate, by difference',
    'fiber': 'Fiber, total dietary',
    'sugar': 'Total sugars',
    'sodium': 'Sodium, Na'
}

def fetch_nutrition_data(food_name: str):
    """
    從 USDA FoodData Central API 獲取食物的營養資訊。

    :param food_name: 要查詢的食物名稱 (例如 "Donuts")。
    :return: 包含營養資訊的字典,如果找不到則返回 None。
    """
    if not USDA_API_KEY:
        logger.error("USDA_API_KEY 未設定,無法查詢營養資訊。")
        return None

    params = {
        'query': food_name,
        'api_key': USDA_API_KEY,
        'dataType': 'Branded',  # 優先搜尋品牌食品,結果通常更符合預期
        'pageSize': 1  # 我們只需要最相關的一筆結果
    }

    try:
        logger.info(f"正在向 USDA API 查詢食物:{food_name}")
        response = requests.get(USDA_API_URL, params=params)
        response.raise_for_status()  # 如果請求失敗 (例如 4xx 或 5xx),則會拋出異常

        data = response.json()

        # 檢查是否有找到食物
        if data.get('foods') and len(data['foods']) > 0:
            food_data = data['foods'][0]  # 取第一個最相關的結果
            logger.info(f"從 API 成功獲取到食物 '{food_data.get('description')}' 的資料")
            
            nutrition_info = {
                "food_name": food_data.get('description', food_name).capitalize(),
                "chinese_name": None,  # USDA API 不提供中文名
            }

            # 遍歷我們需要的營養素
            extracted_nutrients = {key: 0.0 for key in NUTRIENT_MAP.keys()} # 初始化
            
            for nutrient in food_data.get('foodNutrients', []):
                for key, name in NUTRIENT_MAP.items():
                    if nutrient.get('nutrientName').strip().lower() == name.strip().lower():
                        # 將值存入我們的格式
                        extracted_nutrients[key] = float(nutrient.get('value', 0.0))
                        break # 找到後就跳出內層迴圈

            nutrition_info.update(extracted_nutrients)
            
            # 由於 USDA 不直接提供健康建議,我們先回傳原始數據
            # 後續可以在 main.py 中根據這些數據生成我們自己的建議
            return nutrition_info

        else:
            logger.warning(f"在 USDA API 中找不到食物:{food_name}")
            return None

    except requests.exceptions.RequestException as e:
        logger.error(f"請求 USDA API 時發生錯誤: {e}")
        return None
    except Exception as e:
        logger.error(f"處理 API 回應時發生未知錯誤: {e}")
        return None

if __name__ == '__main__':
    # 測試此模組的功能
    test_food = "donuts"
    nutrition = fetch_nutrition_data(test_food)
    if nutrition:
        import json
        print(f"成功獲取 '{test_food}' 的營養資訊:")
        print(json.dumps(nutrition, indent=2))
    else:
        print(f"無法獲取 '{test_food}' 的營養資訊。")