0

0

利用Python高效获取USDA食品营养数据:API分页处理详解

霞舞

霞舞

发布时间:2025-08-28 20:19:00

|

872人浏览过

|

来源于php中文网

原创

利用Python高效获取USDA食品营养数据:API分页处理详解

本教程详细讲解如何利用Python和USDA食品数据中心API获取完整的食品营养数据。针对API默认50条结果的限制,我们将深入探讨API分页机制,包括pageSize和pageNumber参数的使用。通过迭代请求、优化代码结构及错误处理,本文将提供一个高效的解决方案,帮助用户克服API分页限制,全面抓取并处理所有可用的食品营养信息。

理解API分页机制

在使用外部api获取数据时,经常会遇到api对单次请求返回结果数量的限制。这是一种常见的机制,旨在防止单个请求消耗过多服务器资源,并提高api响应速度。usda食品数据中心(fdc)api也不例外,其默认情况下每次请求可能只返回50条结果。

要解决这个问题,关键在于查阅API的官方文档。通过仔细阅读API文档,我们可以发现FDC API支持分页查询,这意味着数据被分割成多个“页面”,每次请求只能获取一个页面的数据。文档中明确指出了两个关键参数:

  • pageSize:定义了每个页面返回结果的最大数量。默认值为50,但根据文档,最大可以设置为200。
  • pageNumber:指定要请求的页面编号。通过递增此参数,可以逐页获取所有数据。

API响应中通常会包含currentPage(当前页码)和totalPages(总页数)等信息,这些信息对于实现完整的数据遍历至关重要。

分页数据获取的Python实现

为了获取所有符合条件的食品营养数据,我们需要编写一个循环,在每次迭代中请求不同的页面,直到所有页面都被访问。以下是实现这一目标的Python代码示例,它对原始请求逻辑进行了优化和扩展。

优化后的API调用函数

import requests
import json
import pandas as pd

def get_all_usda_foods(query_term, api_key):
    """
    通过USDA食品数据中心API获取所有匹配的食品营养数据。
    该函数处理API分页,并返回一个包含所有食品项的列表。

    Args:
        query_term (str): 查询的食品名称或关键词,例如 'raw'。
        api_key (str): 您的USDA API密钥。

    Returns:
        list: 包含所有食品项字典的列表,如果请求失败则返回None。
    """
    all_foods = []
    # 构造基础URL,设置pageSize为最大值200以减少请求次数
    base_url = f"https://api.nal.usda.gov/fdc/v1/foods/search?api_key={api_key}&query={query_term}&pageSize=200"

    with requests.Session() as session: # 使用requests.Session提高效率
        try:
            # 首次请求获取总页数
            print(f"Fetching initial page for query: '{query_term}'...")
            initial_response = session.get(base_url, timeout=10)
            initial_response.raise_for_status() # 检查HTTP请求是否成功
            api_response_data = initial_response.json()

            if not api_response_data.get("foods"):
                print(f"No foods found for query: '{query_term}'.")
                return []

            total_pages = api_response_data.get("totalPages", 1)
            print(f"Total pages to retrieve: {total_pages}")

            all_foods.extend(api_response_data["foods"]) # 添加第一页的数据

            # 遍历剩余页面
            for page_num in range(2, total_pages + 1):
                print(f"Fetching page {page_num}/{total_pages}...")
                page_url = f"{base_url}&pageNumber={page_num}"
                page_response = session.get(page_url, timeout=10)
                page_response.raise_for_status()
                page_data = page_response.json()
                all_foods.extend(page_data["foods"])

        except requests.exceptions.HTTPError as http_err:
            print(f"HTTP error occurred: {http_err} - Status Code: {http_err.response.status_code}")
            return None
        except requests.exceptions.ConnectionError as conn_err:
            print(f"Connection error occurred: {conn_err}")
            return None
        except requests.exceptions.Timeout as timeout_err:
            print(f"Request timed out: {timeout_err}")
            return None
        except requests.exceptions.RequestException as req_err:
            print(f"An unexpected error occurred: {req_err}")
            return None
        except json.JSONDecodeError as json_err:
            print(f"Error decoding JSON response: {json_err}")
            print(f"Response content: {initial_response.text if 'initial_response' in locals() else 'N/A'}")
            return None
    return all_foods

# 替换为您的实际API密钥
API_KEY = "YOUR_USDA_API_KEY" 
food_items = get_all_usda_foods("raw", API_KEY)

if food_items:
    print(f"\nSuccessfully retrieved {len(food_items)} food items.")
    # 后续数据处理...
else:
    print("Failed to retrieve food items or no items found.")

代码解析与优化点

  1. requests.Session的使用: requests.Session对象可以在多次请求中保持某些参数(如cookies、请求头),并且会重用底层的TCP连接,这对于进行多次API请求(如分页)来说,可以显著提高效率和性能。

  2. pageSize参数优化: 我们将pageSize直接设置为API允许的最大值200。这样做可以减少需要发起的API请求总数,从而缩短数据获取时间。

  3. 分页逻辑

    立即学习Python免费学习笔记(深入)”;

    Civitai
    Civitai

    AI艺术分享平台!海量SD资源和开源模型。

    下载
    • 首先发起一个请求来获取第一页的数据,并从响应中提取totalPages(总页数)。
    • 将第一页的数据添加到all_foods列表中。
    • 然后,使用for循环从第2页开始(因为第1页已经获取),一直迭代到totalPages。
    • 在每次循环中,通过添加&pageNumber={page_num}参数来构造新的URL,并发送请求获取当前页的数据。
    • 将每页获取到的foods列表扩展到all_foods中。
  4. 健壮的错误处理

    • try...except块用于捕获各种可能发生的网络和API错误,例如requests.exceptions.HTTPError(HTTP状态码非200)、requests.exceptions.ConnectionError(连接失败)、requests.exceptions.Timeout(请求超时)以及json.JSONDecodeError(JSON解析失败)。
    • response.raise_for_status()是一个便捷的方法,如果HTTP请求返回了错误的状态码(如4xx或5xx),它会抛出一个HTTPError异常。

数据处理与导出

获取到完整的食品数据列表food_items后,下一步就是将其转换为结构化的数据格式(如Pandas DataFrame),并导出到Excel文件。

# 假设food_items已经通过get_all_usda_foods函数获取
if food_items:
    table_data = []
    for food_item in food_items:
        row = {
            "Description": food_item.get("description", "N/A"),
            "FDC_ID": food_item.get("fdcId", "N/A") # 添加FDC ID以便追踪
        }

        # 提取营养成分
        for nutrient in food_item.get("foodNutrients", []):
            nutrient_name = nutrient.get("nutrientName")
            nutrient_value = nutrient.get("value")
            if nutrient_name and nutrient_value is not None:
                row[nutrient_name] = nutrient_value
        table_data.append(row)

    # 创建DataFrame
    df = pd.DataFrame(table_data)

    # 打印一些信息,例如数据框的形状和前几行
    print("\nDataFrame created:")
    print(f"Shape: {df.shape}")
    print("First 5 rows:")
    print(df.head())

    # 导出到Excel
    output_filename = 'usda_nutritional_facts_all.xlsx'
    try:
        df.to_excel(output_filename, index=False)
        print(f"\nData successfully exported to {output_filename}")
    except Exception as e:
        print(f"Error exporting to Excel: {e}")
else:
    print("No data to process or export.")

在这个数据处理阶段,我们:

  1. 遍历food_items列表中的每一个食品字典。
  2. 为每个食品创建一个行字典,包含Description和FDC_ID等基本信息。
  3. 遍历foodNutrients列表,将每个营养成分的名称作为列名,其值作为单元格内容。
  4. 使用pd.DataFrame()将列表中的所有行字典转换为一个Pandas DataFrame。
  5. 最后,使用df.to_excel()方法将DataFrame导出为Excel文件,index=False表示不将DataFrame的索引写入Excel。

注意事项与最佳实践

  • API文档是黄金法则:在与任何API交互之前,务必仔细阅读其官方文档。它是理解API功能、参数、限制和错误代码的唯一权威来源。
  • 错误处理:始终在您的代码中包含健壮的错误处理机制。网络不稳定、API密钥失效、请求参数错误等都可能导致程序崩溃。良好的错误处理能提高程序的稳定性和用户体验。
  • API密钥安全:切勿将API密钥硬编码到公共代码仓库或客户端代码中。应通过环境变量、配置文件或秘密管理服务来安全地存储和访问API密钥。
  • 速率限制:某些API会有请求频率限制(rate limiting),即在一定时间内允许的请求次数。如果超出限制,API会返回错误。虽然USDA FDC API的文档中没有明确提及严格的速率限制,但在进行大量请求时仍需注意。如果遇到此类问题,可能需要引入延迟(time.sleep())来避免被封禁。
  • 数据量考量:如果获取的数据量非常大,一次性加载到内存中可能会导致内存溢出。在这种情况下,可以考虑分批处理数据,或直接将数据流式写入文件,而不是先全部收集到内存中再写入。

总结

通过本教程,我们深入探讨了如何利用Python克服USDA食品数据中心API的分页限制,从而获取完整的食品营养数据。核心在于理解API文档中关于pageSize和pageNumber参数的定义,并结合requests.Session进行高效的迭代请求。同时,我们也强调了错误处理、API密钥安全以及API文档的重要性,这些都是构建健壮、可靠的API客户端程序的关键要素。掌握这些技巧,您将能够更有效地从各类API中提取所需数据。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

720

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

627

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

744

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1236

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

575

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

700

2023.08.11

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 10.3万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号