python3.8 brotli brotli.error: BrotliDecompress a échoué?

Sep 09 2020

mycode python3.8

brotli = 1,0,9

use request get url, les en-têtes utilisent Accept-Encoding = "br" j'ai besoin d'utiliser decode br, parce que je pense utiliser accept-encoding = br plus bon

import brotli
import requests 
headers = {}
headers['Accept'] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
headers['Accept-Encoding'] = "gzip, deflate, br"
headers['Host'] = "book.douban.com"
headers['Referer'] = "book.douban.com"
headers['Sec-Fetch-Dest'] = "document"
headers['Sec-Fetch-Mode'] = "navigate"
headers['Upgrade-Insecure-Requests'] = "1"

s=requests.Session()
url="https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4"
try:
    response = s.get(url, headers=headers)
except:
    return ""
if response.status_code == 200:
    print(response.headers)
    if response.headers.get('Content-Encoding') == 'br':
        data = brotli.decompress(response.content)
        data1 = data.decode('utf-8')
        return data1
    else:
        return response.text
return ""

soulever une erreur

data = brotli.decompress(response.content)
brotli.error: BrotliDecompress failed

Réponses

3 LaurentPinson Nov 03 2020 at 05:11

Ceci n'est mentionné nulle part dans la documentation des requêtes mais une fois brotli installé, il est directement géré par Requests.

Cela signifie que response.content sera automatiquement décodé (comme gzip). Tu n'as pas besoin de fairebrotli.decompress(response.content)

si brotli n'est pas installé, vous n'obtiendrez aucun message d'erreur. Au lieu de cela, response.content restera encodé ...

modifier :

en creusant dans le code des requêtes, j'ai découvert que les requêtes utilisent urllib3.response qui implémente l'utilisation de Brotli.

lors du chargement, urllib3.response recherchera une importation de Brotli:

try:
    import brotli
except ImportError:
    brotli = None

puis lors du décodage d'une réponse, il utilisera un décodeur approprié:

def _get_decoder(mode):
    if "," in mode:
        return MultiDecoder(mode)

    if mode == "gzip":
        return GzipDecoder()

    if brotli is not None and mode == "br":
        return BrotliDecoder()

    return DeflateDecoder()

ainsi si Brotli est installé, le décodage se produira sinon rien ne se passera et aucun avertissement à l'utilisateur.