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

Ash*_*kan 8 python urllib python-3.x python-requests windows-10

我正在尝试使用 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)
Run Code Online (Sandbox Code Playgroud)

实际上它工作正常,但我想改用“请求”库,因为它具有以下代码的代理更新和更灵活:

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)
Run Code Online (Sandbox Code Playgroud)

但它返回403 状态代码,我该如何解决?

请记住,此 API 对所有人开放,您可以放心地运行代码。


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

EDIT-2:我尝试向邮递员请求成功发出请求并返回200 状态代码。邮递员生成了以下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)
Run Code Online (Sandbox Code Playgroud)

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

EDIT-3:我查看了它并发现它适用于 python 2.7.16 但不适用于 python 3.8.5!

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

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

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

小智 3

问题似乎在于主机如何处理 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!
Run Code Online (Sandbox Code Playgroud)