简体   繁体   English

如何使用Python请求库发布帖子请求?

[英]How to make a post request with the Python requests library?

I am using the following filters in Postman to make a POST request in a Web API but I am unable to make a simple POST request in Python with the requests library. 我在Postman中使用以下过滤器在Web API中发出POST请求,但我无法在Python中使用请求库发出简单的POST请求。

First , I am sending a POST request to this URL ( http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets ) with the following filters in Postman applied to the Body, with the raw and JSON(application/json) options selected. 首先 ,我发送一个POST请求到这个URL( http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets ),Postman中的以下过滤器应用于Body,原始和JSON(application / json)选项被选中。

Filters in Postman

{
  "filter": {
    "filters": [
      {
        "field": "RCA_Assigned_Date",
        "operator": "gte",
        "value": "2017-05-31 00:00:00"
      },
      {
        "field": "RCA_Assigned_Date",
        "operator": "lte",
        "value": "2017-06-04 00:00:00"
      },
      {
        "field": "T_Subcategory",
        "operator": "neq",
        "value": "Temporary Degradation"
      },
      {
        "field": "Issue_Status",
        "operator": "neq",
        "value": "Queued"
      }],
     "logic": "and"
    }
}

The database where the data is stored is Cassandra and according to the following links Cassandra not equal operator , Cassandra OR operator , Cassandra Between order by operators , Cassandra does not support the NOT EQUAL TO , OR , BETWEEN operators, so there is no way I can filter the URL with these operators except with AND . 存储数据的数据库是Cassandra,根据以下链接, Cassandra不等于运算符Cassandra OR运算符Cassandra在 运算符 之间 ,Cassandra不支持NOT EQUAL TOORBETWEEN运算符,所以我没办法除了AND之外,可以使用这些运算符过滤URL。

Second , I am using the following code to apply a simple filter with the requests library. 其次 ,我使用以下代码将一个简单的过滤器应用于请求库。

import requests
payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=payload)

But what I've got is the complete data of tickets instead of only those that are not temporary degradation. 但我得到的是门票的完整数据,而不仅仅是那些不是暂时退化的门票。

Third , the system is actually working but we are experiencing a delay of 2-3 mins to see the data. 第三 ,系统实际上正在工作,但我们正在经历2-3分钟的延迟来查看数据。 The logic goes as follows: We have 8 users and we want to see all the tickets per user that are not temporary degradation, then we do : 逻辑如下: 我们有8个用户,我们希望看到每个用户的所有票证都不会暂时降级,然后我们会

def get_json():
    if user_name == "user 001":
        with urllib.request.urlopen(
    "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&001",timeout=15) as url:
            complete_data = json.loads(url.read().decode())

    elif user_name == "user 002":
        with urllib.request.urlopen(             
    "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets?user_name=user&002",timeout=15) as url:
            complete_data = json.loads(url.read().decode())
    return complete_data

def get_tickets_not_temp_degradation(start_date,end_date,complete_):
    return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])

Basically, we get the whole set of tickets from the current and last year, then we let Python to filter the complete set by user and so far there are only 10 users which means that this process is repeated 10 times and makes me no surprise to discover why we get the delay... 基本上,我们从当前和去年获得了整套票,然后我们让Python过滤用户的完整集,到目前为止只有10个用户,这意味着这个过程重复10次并且让我毫不惊讶发现为什么我们得到延迟......

My questions is how can I fix this problem of the requests library? 我的问题是如何解决请求库的这个问题? I am using the following link Requests library documentation as a tutorial to make it working but it just seems that my payload is not being read. 我使用以下链接请求库文档作为教程,使其工作,但似乎我的有效负载没有被读取。

Your Postman request is a JSON body. 你的邮递员请求是一个JSON正文。 Just reproduce that same body in Python. 只需在Python中重现相同的主体即可。 Your Python code is not sending JSON, nor is it sending the same data as your Postman sample. 您的Python代码不发送JSON,也不发送与Postman示例相同的数据。

For starters, sending a dictionary via the data arguments encodes that dictionary to application/x-www-form-urlencoded form, not JSON. 对于初学者来说,通过data参数发送字典会将该字典编码为application/x-www-form-urlencoded形式,而不是JSON。 Secondly, you appear to be sending a single filter. 其次,您似乎发送了一个过滤器。

The following code replicates your Postman post exactly: 以下代码完全复制了您的Postman帖子:

import requests

filters = {"filter": {
    "filters": [{
        "field": "RCA_Assigned_Date",
        "operator": "gte",
        "value": "2017-05-31 00:00:00"
    }, {
        "field": "RCA_Assigned_Date",
        "operator": "lte",
        "value": "2017-06-04 00:00:00"
    }, {
        "field": "T_Subcategory",
        "operator": "neq",
        "value": "Temporary Degradation"
    }, {
        "field": "Issue_Status",
        "operator": "neq",
        "value": "Queued"
    }],
    "logic": "and"
}}

url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
response = requests.post(url, json=filters)

Note that filters is a Python data structure here, and that it is passed to the json keyword argument. 请注意, filters是一个Python数据结构,它传递给json关键字参数。 Using the latter does two things: 使用后者有两件事:

  • Encode the Python data structure to JSON (producing the exact same JSON value as your raw Postman body value). 将Python数据结构编码为JSON(生成与原始Postman体值完全相同的JSON值)。
  • Set the Content-Type header to application/json (as you did in your Postman configuration by picking the JSON option in the dropdown menu after picking raw for the body). Content-Type标头设置为application/json (就像在Postman配置中一样,通过在为主体选择raw之后在下拉菜单中选择JSON选项)。

requests is otherwise just an HTTP API , it can't make Cassandra do any more than any other HTTP library. requests 只是一个HTTP API ,它不能使Cassandra做任何其他HTTP库。 The urllib.request.urlopen code sends GET requests, and are trivially translated to requests with: urllib.request.urlopen代码发送GET请求,并简单地转换为requests

def get_json():
    url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"
    response = requests.get(url, params={'user_name': user}, timeout=15)    
    return response.json()

I removed the if branching and replaced that with using the params argument, which translates a dictionary of key-value pairs to a correctly encoded URL query (passing in the user name as the user_name key). 我删除了if分支并使用params参数替换了它,该params将键值对的字典转换为正确编码的URL查询(将用户名作为user_name键传递)。

Note the json() call on the response; 注意响应的json()调用; this takes care of decoding JSON data coming back from the server. 这将负责解码从服务器返回的JSON数据。 This still takes long, you are not filtering the Cassandra data much here. 这仍然需要很长时间,你不是在这里过滤Cassandra数据。

I would recommend using the json attribute instead of data. 我建议使用json属性而不是数据。 It handles the dumping for you. 它为您处理倾销。

import requests

data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, json=data)

Update, answer for question 3. Is there a reason you are using urllib? 更新,回答问题3.你有没有理由使用urllib? I'd use python requests as well for this request. 我也会对此请求使用python请求。

import requests

def get_json():
    r = requests.get("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets”, params={"user_name": user_name.replace(" ", "&")})

    return r.json

# not sure what you’re doing here, more context/code example would help
def get_tickets_not_temp_degradation(start_date, end_date, complete_):
    return Counter([k['user_name'] for k in complete_data if start_date < dateutil.parser.parse(k.get('DateTime')) < end_date and k['T_subcategory'] != 'Temporary Degradation'])

Also, is the username really supposed to be user+001 and not user&001 or user 001 ? 此外,用户名真的应该是user+001而不是user&001user 001吗?

I think, you can use requests library as follows: 我想,您可以使用请求库,如下所示:

import requests
import json

payload = {'field':'T_Subcategory','operator':'neq','value':'Temporary Degradation'}
url = requests.post("http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets",data=json.dumps(payload))

You are sending user in url, use it through post, but its depend upon how end points are implemented. 您正在使用URL发送用户,通过帖子使用它,但它取决于如何实现端点。 You can try the below code : 您可以尝试以下代码:

import requests
from json import dumps

data = {'user_name':'user&001'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets/"
r = requests.post(url, headers=headers, data=dumps(data))

My experience is the following: I've tried urllib and requests a lot in python to deal with APIs. 我的经验如下:我已经尝试过urllib并在python中请求很多来处理API。 It is just very problematic. 这是非常有问题的。 Usually GET requests are straightfoward, but POST requests are very problematic. 通常GET请求是直接的,但POST请求是非常有问题的。 Sometimes doesn't work (as in your payload case), or worse, it works badly. 有时不起作用(如在你的有效载荷情况下),或者更糟糕的是,它工作得很糟糕。 I had this script recently that passed my tests but it didn't work for some cases on production, until I found out that requests that had special characters (like ã á in portuguese) didnt work. 我最近有这个脚本通过了我的测试,但它对生产的某些情况不起作用,直到我发现有特殊字符的请求(如葡萄牙语中的ã)不起作用。 :( :(
At some point I said 'to hell with this black box dependencies'. 在某些时候,我说'对这个黑盒依赖性来说是地狱'。 As a matter of fact, one can make any API call without python or any other scripting language (well you need bash at least). 事实上,可以在没有python或任何其他脚本语言的情况下进行任何API调用(至少你需要使用bash)。 As a UNIX user one can use CURL for EVERYTHING. 作为UNIX用户,可以将CURL用于一切。 It is liberating! 这是解放! No more examples that doesnt work, no more versions of languages no more http libraries. 没有更多的例子不起作用,没有更多的语言版本没有更多的http库。 I just send a curl request from the terminal and see if what I want works. 我只是从终端发送一个卷曲请求,看看我想要的是什么。 Your case would be: 你的情况是:

curl -H "Content-Type: application/json" -d '{"field":"T_Subcategory","operator":"neq","value":"Temporary Degradation"}' "http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets"

Next I build the following python script for GET: 接下来,我为GET构建以下python脚本:

import subprocess
import json

header1 = "Content-Type: application/json"   
header2 = "app_token: your_token"
header3 = "access_token: your_token2"

url = "https://your_api"
command = ["curl","-s","-H",header1,"-H",header2,"-H",header3, url ]
raw_response = subprocess.check_output(command)
string_response = raw_response.decode('utf8')
data = json.loads(string_response)

For POST: 对于POST:

import subprocess
import json

header1 = "Content-Type: application/json"   
header2 = "app_token: your_token"
header3 = "access_token: your_token2"

data = {"my":"phyton_dictionary"}
data = json.dumps(data) #this is a json string now

url = "https://your_api"
command = ["curl","-s","-H",header1,"-H",header2,"-H",header3, -d, data, url ]
raw_response = subprocess.check_output(command)
string_response = raw_response.decode('utf8')
data = json.loads(string_response)

It is very easy to transform those two prototypes in python functions and make a 'library' as you need other calls. 在python函数中转换这两个原型非常容易,并且在需要其他调用时创建一个“库”。 You can build the URL parameters by hand if you are dealing with an API tha needs that. 如果您正在处理需要的API,则可以手动构建URL参数。

So, this answer does not solve your specific problem with requests. 因此,这个答案并不能解决您的特定问题。 It just tells you that I had many many of those problems, solved a few by trial and error hacking style, and eventually solved the problem by changing the way I build the API script, by removing all dependencies that I could, until I reached a very clean script. 它只是告诉你我有很多这些问题,通过试验和错误黑客风格解决了一些问题,并最终通过改变我构建API脚本的方式,通过删除所有依赖项来解决问题,直到我达到非常干净的脚本。 Never had problems again if the docs have the url that I need to reach and the headers I need to send. 如果文档有我需要访问的URL和我需要发送的标题,那么再也没有问题。

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM