适用于 urrlib.request 但不适用于请求

Works with urrlib.request but doesn't work with requests

我正在尝试使用 post 方法向 API 发送请求,我的代码如下所示:

import urllib.request
import json

url         = "https://api.cloudflareclient.com/v0a745/reg"
referrer    = "e7b507ed-5256-4bfc-8f17-2652d3f0851f"
body        = {"referrer": referrer}
data        = json.dumps(body).encode('utf8')
headers     = {'User-Agent': 'okhttp/3.12.1'}
req         = urllib.request.Request(url, data, headers)
response    = urllib.request.urlopen(req)
status_code = response.getcode()
print (status_code)

实际上它工作正常,但我想使用“requests”库,因为它更新更灵活,使用以下代码的代理:

import requests
import json

url         = "https://api.cloudflareclient.com/v0a745/reg"
referrer    = "e7b507ed-5256-4bfc-8f17-2652d3f0851f"
data        = {"referrer": referrer}
headers     = {'User-Agent': 'okhttp/3.12.1'}
req         = requests.post(url, headers=headers, json=data)
status_code = req.status_code
print (status_code)

但是它 returns 403 状态代码,我该如何解决它?

请记住,此 API 对所有人开放,您只需 运行 代码即可,无需担心。


EDIT-1:我已尝试通过@tomasz-wojcik 建议从第二个代码中删除 json.dumps(body).encode('utf8') 或只是 .encode('utf8') 但我仍然得到403 而第一个代码仍然有效!

EDIT-2:我尝试用 postman 请求成功发出请求并返回 200 状态码 。 postman 生成了以下 python 代码:

import requests

url = "https://api.cloudflareclient.com/v0a745/reg"

payload = "{\"referrer\": \"e7b507ed-5256-4bfc-8f17-2652d3f0851f\"}"
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'User-Agent': 'okhttp/3.12.1',
  'Host': 'api.cloudflareclient.com'
}

response = requests.request("POST", url, headers=headers, data=payload)

status_code = response.status_code
print (status_code)

如果你 运行 postman 之外的代码,它仍然 returns 403 状态码 ,我有点困惑,我在想也许“请求”库不会更改第二个代码中的用户代理。

EDIT-3:我调查了一下,发现它适用于 python 2.7.16 但不适用于 python 3.8.5!

EDIT-4:一些开发人员报告说第二个代码也适用于 python 3.6,但主要的是为什么它适用于其他版本而不是在 3.8 或 3.7 上工作?

Python 返回 403 状态码(第二个代码)的版本:3.8.5 & 3.7

Python 返回 200 状态码(第二个代码)的版本:3.6 & 2.7.16

问题似乎与主机处理 ssl 的方式有关。较新版本的请求使用 certifi,在您的情况下,主机服务器存在问题。我将请求降级到较早的版本并且它有效。 (2.1.0)。您可以修复 requirements.txt 中的版本,它应该适用于任何 python 版本。

https://requests.readthedocs.io/en/master/user/advanced/#ca-certificates


Before version 2.16, Requests bundled a set of root CAs that it trusted, sourced from the Mozilla trust store. 
The certificates were only updated once for each Requests version. When certifi was not installed, this led to extremely out-of-date certificate bundles when using significantly older versions of Requests.

For the sake of security we recommend upgrading certifi frequently!