关于API GET调用中的身份验证的问题

时间:2019-10-10 20:01:05

标签: api httr

我正在尝试使用USDA网站上描述的Food Data Central REST API访问基本食品信息:

Food Data Central API Guide

对于该项目,我使用R中的 httr (v 1.3.1)程序包进行通话。

API调用的文档看起来不错,并提供了一些示例。不幸的是,这些示例都没有使用R,并且由于我对API开发知之甚少,所以我不确定文档的“内容”应如何转化为我。该文档提供以下示例:

curl -H "Content-Type:application/json"

-d '{"generalSearchInput":"Cheddar cheese"}'

-X POST

https://DEMO_KEY@api.nal.usda.gov/fdc/v1/search

我看到一个“ Content-Type”标题和一个正文,其中将字符串“ Cheddar cheese”带到了名为 generalSearchInput 的参数中。看来我还需要用自己的API密钥替换'DEMO_KEY'字符串。

我宁愿不共享自己的API密钥,而是it's painless to request one(单击链接,输入名称/电子邮件,几秒钟后获得密钥,甚至不必确认电子邮件)。

以下是我尝试在 httr 包中复制此调用的信息:

httr::POST(url = "https://api.nal.usda.gov/fdc/v1/search", 
           authenticate(user = "<MyAPIKey>", password = "", type = "basic"),
           query = list(generalSearchInput = "Cheddar cheese",
           encode = "json")

)

具有以下响应:

Response [https://api.nal.usda.gov/fdc/v1/search]
  Date: 2019-10-10 20:34
  Status: 403
  Content-Type: application/json
  Size: 141 B
{
  "error": {
    "code": "API_KEY_INVALID",
    "message": "An invalid api_key was supplied. Get one at https://api.nal.usda.gov:443"
  }

这也许不足为奇。我遇到了一些问题:

如何正确将API密钥传递给调用?我尝试使用基本的HTTP身份验证as described on the api.data.gov website documentation(例如,密钥作为用户名和一个空密码)来执行此操作,但我认为我没有正确执行此操作。

2 个答案:

答案 0 :(得分:1)

根据documentation,您可以通过以下方式将JSON数据包括在POST请求的正文中:

httr::POST(
    url = "https://api.nal.usda.gov/fdc/v1/search", 
    authenticate(user = "<MyAPIKey>", password = "", type = "basic"),
    body = list(generalSearchInput = "Cheddar cheese"),
    encode = "json"
)

答案 1 :(得分:0)

不确定您是否仍在进行此操作,但是我从Github上的某人那里找到的这段代码可能会有所帮助。它一直在为我工作。您只需要填写apiKey和特定的foodID。

导入请求 导入json 将熊猫作为pd导入#如果您想将响应添加到数据框以使其更易于使用(此处未显示该代码)

apiKey =''

foodID =''

def culture_API(apiKey,foodID): #calls获取api和json加载 api_resp = json.loads(requests.get('https://api.nal.usda.gov/fdc/v1/'+ foodID +'?api_key ='+ apiKey).text) #只返回营养信息 api_ Nutritions = api_resp ['foodNutrients'] #first条目是其描述,foodID和数据库条目类型 NutritionDict = {“ FoodID”:[api_resp ['description'],foodID,api_resp ['dataType']]}

for items in api_nutrients:
    if 'amount' in items:
        #each entry includes nutrient name, nutrient id, amount, and its respective unit
        nutrientDict.update({(items['nutrient']['name']): [(items['nutrient']['id']),
            (items['amount']),(items['nutrient']['unitName'])]})
    #print(nutrientDict)
return(nutrientDict)