使用python向RESTful API发出请求


221

我有一个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(不确定要使用哪一个-一直在使用urllib2,但听说请求更好……)将以上转换为API请求?我是否可以通过标题?

Answers:


340

使用请求

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先检查)。请参阅此处的快速入门文档,尤其是本节


3
我认为应该是:response =
request.post

8
“ requests.get”不采用“ data”参数。它可以使用可选的“ params”参数,该参数通常是一个带有查询字符串的字典。如果需要有效负载来获取数据(例如所讨论的示例),则需要使用“ requests.post”。另外,使用“ json”库可以更轻松地解析json响应。
HVS 2016年

4
@ParveenShukhala“请求正式支持Python 2.6–2.7和3.3–3.5,并且在PyPy上运行良好。” - pypi.python.org/pypi/requests
斑马鱼

2
由于您要发送的是JSON,因此可以使用json参数而不是像这样的数据:response = requests.post(url,json = data)
Mark Chorley,

101

使用请求json使其变得简单。

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

请求模块为您提供有用的功能,以循环执行成功和失败。

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()

2
在键上进行迭代的最后部分将始终无法工作,因为JSON文档可能会将数组作为顶级元素。因此,尝试获取将是一个错误jData[key]
Denis The Menace

@DenisTheMenace如果它是一个数组,我将如何循环它?
qasimalbaqali

@qasimalbaqali与您遍历字典的方式相同。但数组元素将是简单地jData,不jData[key]
丹尼斯的威胁

旁注:如果您的API返回大型JSON响应,则可以像这样漂亮地打印出来: print(json.dumps(jData, indent=4, sort_keys=True))
Marco Marco

2
在python3下,以下内容被吐出:“ JSON必须是str而不是字节”。通过解码输出即json.loads(myResponse.content.decode('utf-8'))可以解决此问题。另外,您还应该使用str()包装键和jData键,以便当RESTful API返回整数时,它不会抱怨。
Mirkules

11

因此,您想在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()

那里有一个死链接
user3157940

4
应该使用headers变量:requests.get(... headers = headers,....)
Markus Meyer

9

以下是在python-中执行其余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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.