
在使用任何外部api时,查阅其官方文档是至关重要的一步。对于usda食品数据中心(fdc)api,当您通过foods/search端点查询数据时,可能会发现每次请求默认只返回50条结果,即使符合条件的数据远超此数量。这是因为api采用了分页(pagination)机制来管理大量数据的传输。
API响应中通常会包含以下关键信息,指示分页状态:
API文档明确指出,pageSize参数的默认值为50,但最大可以设置为200。同时,可以通过pageNumber参数指定要获取的页码。这意味着要获取所有符合条件的数据,我们需要执行一系列请求,每次请求不同的页码,直到所有页面都被遍历。
为了克服50条结果的限制并获取完整数据集,我们需要采取以下策略:
以下是一个优化后的Python函数,它封装了上述策略,能够从USDA FDC API完整地获取指定食物的营养数据。
立即学习“Python免费学习笔记(深入)”;
import requests
import json
import pandas as pd
import time # 引入time模块用于模拟请求间隔
def get_all_food_data(query_name: str, api_key: str, max_page_size: int = 200) -> list:
"""
通过USDA FDC API获取指定查询名称的所有食品数据,处理分页。
Args:
query_name (str): 查询的食物名称,例如 'raw'。
api_key (str): 您的USDA API密钥。
max_page_size (int): 每页最大结果数,默认为200。
Returns:
list: 包含所有食品数据的列表,每个元素是一个字典。
如果获取失败,返回None。
"""
all_foods = []
base_url = "https://api.nal.usda.gov/fdc/v1/foods/search"
# 使用requests.Session来重用TCP连接,提高效率
with requests.Session() as session:
# 构建初始请求URL,设置最大pageSize
initial_url = f"{base_url}?api_key={api_key}&query={query_name}&pageSize={max_page_size}"
try:
print(f"开始获取 '{query_name}' 的数据...")
# 发送第一个请求以获取总页数和第一页数据
response = session.get(initial_url, timeout=15)
response.raise_for_status() # 检查HTTP响应状态码,如果不是200,则抛出异常
api_response_json = response.json()
# 检查API响应中是否存在'foods'键
if 'foods' not in api_response_json or not api_response_json['foods']:
print(f"未找到 '{query_name}' 的食品数据或API响应格式异常。")
return []
all_foods.extend(api_response_json["foods"])
total_pages = api_response_json.get("totalPages", 1)
print(f"总共找到 {api_response_json.get('totalHits', 0)} 条结果,分布在 {total_pages} 页。")
# 从第二页开始循环获取所有剩余页面
for page_num in range(2, total_pages + 1):
page_url = f"{initial_url}&pageNumber={page_num}"
print(f"正在获取第 {page_num}/{total_pages} 页数据...")
# 建议在每次请求之间添加短暂的延迟,以避免API限流
time.sleep(0.1)
page_response = session.get(page_url, timeout=15)
page_response.raise_for_status()
page_api_response_json = page_response.json()
if 'foods' in page_api_response_json:
all_foods.extend(page_api_response_json["foods"])
else:
print(f"警告:第 {page_num} 页API响应中未包含 'foods' 键。")
except requests.exceptions.HTTPError as http_err:
print(f"HTTP错误发生: {http_err} - URL: {response.url}")
return None
except requests.exceptions.ConnectionError as conn_err:
print(f"连接错误发生: {conn_err}")
return None
except requests.exceptions.Timeout as timeout_err:
print(f"请求超时: {timeout_err}")
return None
except requests.exceptions.RequestException as req_err:
print(f"请求发生未知错误: {req_err}")
return None
except json.JSONDecodeError as json_err:
print(f"JSON解析错误: {json_err} - 响应内容: {response.text[:200]}...")
return None
except Exception as e:
print(f"发生意外错误: {e}")
return None
print(f"成功获取所有 {len(all_foods)} 条食品数据。")
return all_foods
# --- 使用示例 ---
if __name__ == "__main__":
YOUR_API_KEY = "YOUR_USDA_API_KEY" # 替换为您的实际API密钥
SEARCH_QUERY = "apple" # 替换为您想查询的食物
# 1. 调用函数获取所有食品数据
food_items = get_all_food_data(SEARCH_QUERY, YOUR_API_KEY)
if food_items:
# 2. 将获取到的数据转换为Pandas DataFrame
table_data = []
for food_item in food_items:
row = {
"Description": food_item.get("description", "N/A"),
"FDC_ID": food_item.get("fdcId", "N/A")
}
# 提取营养成分,注意有些食品可能没有所有营养成分
for nutrient in food_item.get("foodNutrients", []):
nutrient_name = nutrient.get("nutrientName")
value = nutrient.get("value")
if nutrient_name and value is not None:
row[nutrient_name] = value
table_data.append(row)
df = pd.DataFrame(table_data)
# 3. 导出到Excel
output_filename = f'{SEARCH_QUERY}_nutritional_facts.xlsx'
try:
df.to_excel(output_filename, index=False)
print(f"数据已成功导出到 '{output_filename}'")
print(f"DataFrame的最后一行数据:\n{df.iloc[-1]}")
except Exception as e:
print(f"导出Excel失败: {e}")
else:
print("未能获取食品数据,无法生成Excel文件。")
通过本教程,我们深入理解了USDA FDC API的分页机制,并学习了如何通过Python编写健壮的代码来完整地获取所有符合条件的营养数据。核心在于利用API提供的 pageSize 和 pageNumber 参数进行迭代请求,同时结合 requests.Session 提高效率,并加入全面的错误处理。掌握这一技巧,您将能够更有效地从分页API中提取所需的所有信息,为后续的数据分析和应用打下坚实基础。
以上就是Python利用USDA API获取完整营养数据:深度解析分页机制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号