使用 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/requests
或python/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.text
或response.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 请求