【问题标题】:How to make a post request with the Python requests library?如何使用 Python requests 库发出 post 请求?
【发布时间】:2017-12-25 09:05:11
【问题描述】:

我在 Postman 中使用以下过滤器在 Web API 中发出 POST 请求,但我无法在 Python 中使用 requests 库发出简单的 POST 请求。

首先,我正在向该 URL (http://10.61.202.98:8081/T/a/api/rows/cat/ect/tickets) 发送一个 POST 请求,其中 Postman 中的以下过滤器应用于正文,并选择了 raw 和 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"
    }
}

存储数据的数据库是Cassandra,根据以下链接Cassandra not equal operator,Cassandra OR operator, Cassandra Between order by operators,Cassandra 不支持 NOT EQUAL TOORBETWEEN 运算符,所以我无法使用除了 AND 之外的这些运算符。

第二,我正在使用以下代码对请求库应用一个简单的过滤器。

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)

但我得到的是完整的票证数据,而不是只有那些不是临时降级的数据。

第三,系统实际上正在运行,但我们会遇到 2-3 分钟的延迟才能看到数据。逻辑如下:我们有 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'])

基本上,我们得到了今年和去年的整套票,然后我们让 Python 按用户过滤完整集,到目前为止只有 10 个用户,这意味着这个过程重复了 10 次,让我毫不奇怪地发现为什么我们会延迟......

我的问题是如何解决 requests 库的这个问题?我正在使用以下链接 Requests library documentation 作为教程来使其正常工作,但似乎我的有效负载没有被读取。

【问题讨论】:

  • 在使用 JSON 数据时,我很幸运使用 json 关键字 arg 代替了 data
  • json=payload替换data=payload
  • 我没有运气将 data=payload 更改为 json=payload :(
  • 那么 Postman 查询是否有效 还是无效?
  • 您的问题也令人困惑。如果 cassandra 不支持某些过滤器操作,那么这不是 requests 限制。您只能发送 cassandra 支持的查询,仅此而已。

标签: python json django python-3.x cassandra


【解决方案1】:

您的 Postman 请求是 JSON 正文。只需在 Python 中重现相同的主体。您的 Python 代码没有发送 JSON,也没有发送与 Postman 示例相同的数据。

对于初学者,通过data 参数发送字典会将字典编码为application/x-www-form-urlencoded 形式,而不是JSON。其次,您似乎发送了一个过滤器。

以下代码完全复制了您的 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)

注意filters 在这里是一个Python 数据结构,它被传递给json 关键字参数。使用后者有两件事:

  • 将 Python 数据结构编码为 JSON(生成与原始 Postman 正文值完全相同的 JSON 值)。
  • Content-Type 标头设置为 application/json(就像您在 Postman 配置中所做的那样,在为正文选择 raw 后,在下拉菜单中选择 JSON 选项)。

requests 否则只是一个 HTTP API,它不能让 Cassandra 比任何其他 HTTP 库做得更多。 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()

我删除了 if 分支并使用 params 参数替换了它,它将键值对字典转换为正确编码的 URL 查询(将用户名作为 user_name 键传递)。

注意响应中的json() 调用;这负责解码从服务器返回的 JSON 数据。这仍然需要很长时间,您在这里没有太多过滤 Cassandra 数据。

【讨论】:

    【解决方案2】:

    我建议使用json 属性而不是数据。它会为您处理倾销。

    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)
    

    更新,回答问题 3。您使用 urllib 有什么原因吗?对于这个请求,我也会使用 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'])
    

    另外,用户名真的应该是user+001 而不是user&amp;001user 001

    【讨论】:

      【解决方案3】:

      您在 url 中发送用户,通过 post 使用它,但这取决于端点的实现方式。你可以试试下面的代码:

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

      【讨论】:

        【解决方案4】:

        我认为,您可以按如下方式使用请求库:

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

        【讨论】:

        • 我这里有新东西:Message: The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.
        • 我设法通过使用以下方法解决了这个问题:headers = {'Content-type': 'application/json', 'Accept':'text/plain'} 然后r = requests.post(url,data=json.dumps(payload),headers=headers) 但似乎帖子检索了所有数据。
        • 您实际上可以只指定json={“whoami”: “I’m a python dict”} 而不是data=json.dumps...
        猜你喜欢
        • 1970-01-01
        • 2015-06-11
        • 2019-01-11
        • 2022-01-17
        • 2018-02-09
        • 2013-03-12
        • 1970-01-01
        • 2020-03-23
        • 2015-05-18
        相关资源
        最近更新 更多