Permintaan get / post sederhana diblokir dalam python 3 tetapi tidak dalam python 2

19

Saya sedang mengerjakan scraper web sederhana dengan python 3 tetapi ketika saya mengirim get atau permintaan posting, jawabannya adalah 403. Namun, dalam python 2 berfungsi dengan baik. Saya menggunakan versi yang sama dari perpustakaan permintaan di kedua versi. Saya juga sudah mencoba Verify=False/Truetetapi perbedaan di kedua versi tetap.

permintaan = 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

Edit oleh @blhsing:

Daftar di bawah ini melacak versi Python spesifik mana yang bekerja dan versi mana yang gagal sesuai dengan komentar. Sejauh ini keberhasilan dan kegagalan telah konsisten untuk setiap versi Python spesifik di seluruh platform.

Jangan ragu untuk mengedit bagian pertanyaan ini dengan hasil Anda sendiri bersama dengan versi Python spesifik yang digunakan untuk menghasilkan hasil.

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 di repl.it: Python 2.7.16 dan Python 3.7.4

EDM
sumber
Perlu dicatat bahwa ini berfungsi dalam Python 3.6 tetapi tidak dalam 3.7.
Blhsing
Saya mendapatkan "Akses Ditolak" bahkan di Firefox - setelah beberapa menjalankan kode dengan Python 3.7. Saya tidak mencoba di Firefox sebelum menjalankan Python - mungkin saya diblokir setelah menggunakan kode Python atau mungkin memblokir karena alasan lain - IP salah, negara salah, masalah pada server.
furas
1
@blhsing ya itu aneh, saya kira saya akan pergi dengan 3,6 kemudian, terima kasih
EDM
2
Itu aneh. Gunakan Wireshark dan bandingkan permintaan yang dikirim oleh Python 3.6 dan 3.7. Pasti ada beberapa perbedaan yang diangkat server.
GordonAitchJay
1
Maka itu mungkin karena openssl berbeda ( ssl.OPENSSL_VERSION). Anda tidak perlu semua tajuk itu untuk ditegur, hanya mendapatkan (url) lama yang biasa akan melakukannya.
wim

Jawaban:

9

Ini adalah pengecualian yang dilemparkan oleh urlib3:

/home/runner/.local/share/virtualenvs/python3/lib/python3.7/site-packages/urllib3/connectionpool.py:1004: InsecureRequestWarning: Permintaan HTTPS tidak diverifikasi sedang dibuat. Menambahkan verifikasi sertifikat sangat disarankan. Lihat: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning,

Menurut catatan rilis terbaru, bagian 1.25.5 (2019-09-19) :

Tambahkan mitigasi untuk BPO-37428 yang memengaruhi Python <3.7.4 dan OpenSSL 1.1.1+ yang menyebabkan verifikasi sertifikat diaktifkan saat menggunakan cert_reqs = CERT_NONE. (Masalah # 1682 )

Anda dapat mengikuti masalah di Github , telah ditutup.

TLDR

Pengguna @sethmlarson di Github menemukan bug ini di 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

mengatur nilai ini ke Trueakan memungkinkan verifikasi sertifikat server, bukannya dinonaktifkan.

Naor Tedgi
sumber