Proste żądanie get / post zablokowane w Pythonie 3, ale nie w Pythonie 2

19

Pracuję na prostym skrobaku internetowym w Pythonie 3, ale kiedy wysyłam żądanie get lub post, odpowiedź wynosi 403. W Pythonie 2 działa jednak dobrze. Używam tej samej wersji bibliotek żądań w obu wersjach. Próbowałem też z, Verify=False/Trueale różnica w obu wersjach pozostaje.

żądania = 2.22.0

certifi = 2019.9.11

from requests import get
url = 'https://www.gamestop.com/'
header = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.5',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0',
    'DNT': '1',
    'Upgrade-Insecure-Requests': '1',
    'Connection': 'keep-alive',
    'Host': 'www.gamestop.com'
}
res = get(url, headers=header, verify=False).status_code
print(res)
# 403 when using python 3.7.4
# 200 when using python 2.7.16

Edytuj przez @blhsing:

Poniższa lista śledzi, które konkretne wersje Pythona działają, a które nie działają zgodnie z komentarzami. Dotychczasowe sukcesy i niepowodzenia były spójne dla każdej konkretnej wersji Pythona na różnych platformach.

Edytuj tę sekcję pytania z własnymi wynikami wraz z konkretnymi wersjami języka Python użytymi do wygenerowania wyników.

2.7.14 works (blhsing)
2.7.16 works (repl.it)
3.6.5 works (blhsing)
3.6.8 fails (Reinderien and blhsing)
3.7.3 works (wim and blhsing)
3.7.4 fails (repl.it and blhsing)
3.8.0 fails (OP)

Demo na repl.it: Python 2.7.16 i Python 3.7.4

EDM
źródło
Należy zauważyć, że działa to w Pythonie 3.6, ale nie w 3.7.
blhsing
Dostaję „Odmowa dostępu” nawet w Firefoksie - po kilku uruchomieniach kodu w Pythonie 3.7. Nie próbowałem w Firefoksie przed uruchomieniem Pythona - może jestem zablokowany po użyciu kodu Python lub może blokuje się z innego powodu - zły adres IP, zły kraj, problem na serwerze.
furas
1
@ Blhsing tak, to dziwne, myślę, że pójdę z 3.6 wtedy, dziękuję za uwagę
EDM
2
To jest dziwne. Użyj Wireshark i porównaj żądania wysłane przez Python 3.6 i 3.7. Musi być jakaś różnica, na którą serwer się zbiera.
GordonAitchJay
1
Prawdopodobnie wynika to z różnych openssl ( ssl.OPENSSL_VERSION). Nie potrzebujesz wszystkich tych nagłówków, aby to zrobić, wystarczy zwykły stary get (url).
wim

Odpowiedzi:

9

Jest to wyjątek zgłoszony przez urlib3:

/home/runner/.local/share/virtualenvs/python3/lib/python3.7/site-packages/urllib3/connectionpool.py:1004: InsecureRequestWarning: Tworzone jest niezweryfikowane żądanie HTTPS. Zaleca się dodanie weryfikacji certyfikatu. Zobacz: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning,

Zgodnie z najnowszymi informacjami o wersji, sekcja 1.25.5 (2019-09-19) :

Dodaj ograniczenie dla BPO-37428 wpływającego na Pythona <3.7.4 i OpenSSL 1.1.1+, które spowodowały włączenie weryfikacji certyfikatu podczas korzystania z cert_reqs = CERT_NONE. (Numer 1682 )

Możesz śledzić ten problem na Githubie , został on zamknięty.

TLDR

Użytkownik @sethmlarson na Github znalazł ten błąd na urllib3 :

create_urllib3_context ():

    # Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is
    # necessary for conditional client cert authentication with TLS 1.3.
    # The attribute is None for OpenSSL <= 1.1.0 or does not exist in older
    # versions of Python.
    if getattr(context, "post_handshake_auth", None) is not None:
        context.post_handshake_auth = True

ustawienie tej wartości, aby Truewłączyć weryfikację certyfikatów serwera, zamiast być wyłączone.

Naor Tedgi
źródło