Работает с urrlib.request, но не работает с запросами - PullRequest
8 голосов
/ 03 августа 2020

Я пытаюсь отправить запрос с помощью метода 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)

На самом деле он работает нормально, но я хочу использовать вместо этого библиотеку запросов, поскольку она более обновленный и более гибкий прокси со следующим кодом:

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)

Но он возвращает 403 код состояния , как я могу это исправить?

Имейте в виду, что это API открыт для всех, и вы можете просто запустить код, не беспокоясь.

EDIT-1 : я попытался удалить json.dumps(body).encode('utf8') или просто .encode('utf8') из второго кода по совету @ tomasz-wojcik, но я все еще получаю 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)

Если вы запустите код вне почтальона, он все равно вернет 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

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

Проблема, похоже, в том, как хост обрабатывает ssl. Более новые версии запросов используют certifi, который в вашем случае имеет проблемы с хост-сервером. Я понизил запросы до более ранней версии, и это сработало. (2.1.0). Вы можете исправить версию в файле requirements.txt, и он должен работать с любой версией python.

https://requests.readthedocs.io/en/master/user/advanced/#ca -сертификаты


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!
0 голосов
/ 06 августа 2020

Как объяснено в запросы документов , используйте

body        = {"referrer": referrer}
data        = json.dumps(body)  # Please note that .encode() is useless here
req         = requests.post(url, headers=headers, data=data)

или

body        = {"referrer": referrer}
req         = requests.post(url, headers=headers, json=body)

Но не используйте оба json.dumps и requests.post(). json атрибут. Выберите между выполнением сериализации самостоятельно или позвольте запросам сделать всю работу за вас, но не делайте это дважды.

...