python3.8 brotli brotli.error: BrotliDecompress не удалось?

Sep 09 2020

мой код python3.8

brotli = 1.0.9

используйте запрос на получение URL, в заголовках используется Accept-Encoding = "br", мне нужно использовать decode br, потому что я думаю, что использовать accept-encoding = br лучше

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 ""

поднять ошибку

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

Ответы

3 LaurentPinson Nov 03 2020 at 05:11

Это нигде не упоминается в документации запросов, но после установки brotli это напрямую обрабатывается запросами.

Это означает, что response.content будет автоматически декодирован (аналогично gzip). Вам не нужно делатьbrotli.decompress(response.content)

если brotli не установлен, вы не получите сообщения об ошибке. Вместо этого response.content останется закодированным ...

редактировать :

Покопавшись в коде запросов, я обнаружил, что запросы используют urllib3.response, который реализует использование Brotli.

при загрузке urllib3.response будет искать импорт Brotli:

try:
    import brotli
except ImportError:
    brotli = None

затем при декодировании ответа он будет использовать соответствующий декодер:

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()

таким образом, если Brotli установлен, произойдет декодирование, иначе ничего не произойдет и не будет предупреждений для пользователя.