使用 python 向 RESTful API 发出请求

Posted

技术标签:

【中文标题】使用 python 向 RESTful API 发出请求【英文标题】:Making a request to a RESTful API using python 【发布时间】:2013-06-22 12:31:32 【问题描述】:

我有一个 RESTful API,我使用 EC2 实例上的 Elasticsearch 实现公开了它来索引内容语料库。我可以通过在我的终端 (MacOSX) 上运行以下命令来查询搜索:

curl -XGET 'http://ES_search_demo.com/document/record/_search?pretty=true' -d '
  "query": 
    "bool": 
      "must": [
        
          "text": 
            "record.document": "SOME_JOURNAL"
          
        ,
        
          "text": 
            "record.articleTitle": "farmers"
          
        
      ],
      "must_not": [],
      "should": []
    
  ,
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": 
'

如何使用python/requestspython/urllib2 将上述请求转换为API 请求(不确定该选择哪一个- 一直在使用urllib2,但听说请求更好......)?我是作为标题传递还是以其他方式传递?

【问题讨论】:

【参考方案1】:

使用requests:

import requests
url = 'http://ES_search_demo.com/document/record/_search?pretty=true'
data = '''
  "query": 
    "bool": 
      "must": [
        
          "text": 
            "record.document": "SOME_JOURNAL"
          
        ,
        
          "text": 
            "record.articleTitle": "farmers"
          
        
      ],
      "must_not": [],
      "should": []
    
  ,
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": 
'''
response = requests.post(url, data=data)

根据您的 API 返回的响应类型,您可能需要查看response.textresponse.json()(或者可能首先检查response.status_code)。请参阅快速入门文档here,尤其是this section。

【讨论】:

@ParveenShukhala “Requests 正式支持 Python 2.6–2.7 和 3.3–3.5,并且在 PyPy 上运行良好。” -- pypi.python.org/pypi/requests 由于您发送的是 JSON,因此您可以使用 json 参数而不是像这样的数据:response = requests.post(url, json=data)【参考方案2】:

使用requests 和json 让事情变得简单。

    调用 API 假设 API 返回一个 JSON,将 JSON 对象解析为 Python dict 使用json.loads 函数 遍历字典以提取信息。

Requests 模块为您提供有用的函数来循环成功和失败。

if(Response.ok):将帮助您确定您的 API 调用是否成功(响应码 - 200)

Response.raise_for_status() 将帮助您获取从 API 返回的 http 代码。

以下是进行此类 API 调用的示例代码。也可以在github 中找到。该代码假定 API 使用摘要式身份验证。您可以跳过此步骤或使用其他适当的身份验证模块来对调用 API 的客户端进行身份验证。

#Python 2.7.6
#RestfulClient.py

import requests
from requests.auth import HTTPDigestAuth
import json

# Replace with the correct URL
url = "http://api_url"

# It is a good practice not to hardcode the credentials. So ask the user to enter credentials at runtime
myResponse = requests.get(url,auth=HTTPDigestAuth(raw_input("username: "), raw_input("Password: ")), verify=True)
#print (myResponse.status_code)

# For successful API call, response code will be 200 (OK)
if(myResponse.ok):

    # Loading the response data into a dict variable
    # json.loads takes in only binary or string variables so using content to fetch binary content
    # Loads (Load String) takes a Json file and converts into python data structure (dict or list, depending on JSON)
    jData = json.loads(myResponse.content)

    print("The response contains 0 properties".format(len(jData)))
    print("\n")
    for key in jData:
        print key + " : " + jData[key]
else:
  # If response code is not ok (200), print the resulting http error code with description
    myResponse.raise_for_status()

【讨论】:

对键进行迭代的最后部分并不总是有效,因为 JSON 文档可能将数组作为***元素。因此,尝试获取jData[key] 将是错误的 @DenisTheMenace 如果它是一个数组,我将如何循环它? @qasimalbaqali 与遍历字典的方式相同。但是数组元素只是jData,而不是jData[key] 旁注:如果您的 API 返回较大的 JSON 响应,您可以像这样打印它:print(json.dumps(jData, indent=4, sort_keys=True)) 在python3下,吐出'JSON must be str not bytes'。这可以通过解码输出来解决,即 json.loads(myResponse.content.decode('utf-8'))。你也应该用 str() 包装 key 和 jData 键,所以当 RESTful API 返回整数时,它不会抱怨。【参考方案3】:

因此,您想在 GET 请求的正文中传递数据,最好在 POST 调用中进行。您可以通过使用这两个请求来实现这一点。

原始请求

GET http://ES_search_demo.com/document/record/_search?pretty=true HTTP/1.1
Host: ES_search_demo.com
Content-Length: 183
User-Agent: python-requests/2.9.0
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate


  "query": 
    "bool": 
      "must": [
        
          "text": 
            "record.document": "SOME_JOURNAL"
          
        ,
        
          "text": 
            "record.articleTitle": "farmers"
          
        
      ],
      "must_not": [],
      "should": []
    
  ,
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": 

请求调用示例

import requests

def consumeGETRequestSync():
data = '
  "query": 
    "bool": 
      "must": [
        
          "text": 
            "record.document": "SOME_JOURNAL"
          
        ,
        
          "text": 
            "record.articleTitle": "farmers"
          
        
      ],
      "must_not": [],
      "should": []
    
  ,
  "from": 0,
  "size": 50,
  "sort": [],
  "facets": 
'
url = 'http://ES_search_demo.com/document/record/_search?pretty=true'
headers = "Accept": "application/json"
# call get service with headers and params
response = requests.get(url,data = data)
print "code:"+ str(response.status_code)
print "******************"
print "headers:"+ str(response.headers)
print "******************"
print "content:"+ str(response.text)

consumeGETRequestSync()

【讨论】:

那里有一个死链接 headers 变量应该被使用:requests.get(...headers = headers, ....)【参考方案4】:

下面是python中执行rest api的程序-

import requests
url = 'https://url'
data = '  "platform":     "login":       "userName": "name",      "password": "pwd"       '
response = requests.post(url, data=data,headers="Content-Type": "application/json")
print(response)
sid=response.json()['platform']['login']['sessionId']   //to extract the detail from response
print(response.text)
print(sid)

【讨论】:

以上是关于使用 python 向 RESTful API 发出请求的主要内容,如果未能解决你的问题,请参考以下文章

向我的 RESTful API(Python-Flask)发送 POST 请求,但收到 GET 请求

Python API:使用没有文件的媒体发推文

细说RESTFul API之版本管理

使用 Python 和 Flask 设计 RESTful API

FlaskFlask Restful api

Restful API应遵循哪些规范?Python进阶