Python-запросы выдают сбой соединения: ChunkedEncodingError с http.client.IncompleteRead при попытке загрузить файл - PullRequest
0 голосов
/ 02 октября 2019

Я пытаюсь скачать файл PDF с помощью модуля запросов, код выглядит следующим образом:

import requests

url = "<url of the pdf>"
r = requests.get(url, stream=True, timeout=(60, 120), headers={'Connection': 'keep-alive','User-Agent': 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136'})

print(r.headers)
print(r.status_code)

try:
    with open('blah.pdf', 'wb') as f:
        for chunk in r:
            # print(chunk)
            f.write(chunk)
except Exception as e:
    print(e)

Вывод приведен ниже:

{'Cache-Control': 'private', 'Transfer-Encoding': 'chunked', 'Content-Type': 'application/pdf', 'Server': 'Microsoft-IIS/7.5', 'X-AspNet-Version': '4.0.30319', 'X-Powered-By': 'ASP.NET', 'Date': 'Wed, 02 Oct 2019 05:17:11 GMT', 'Set-Cookie': 'bbb=rd102o00000000000000000000ffff978433aao80; path=/; Httponly; Secure'}
200
('Connection broken: IncompleteRead(0 bytes read, 2 more expected)', IncompleteRead(0 bytes read, 2 more expected))

Вот полныйтрассировка стека:

Traceback (most recent call last):
  File "/storage/anaconda3/lib/python3.7/site-packages/urllib3/response.py", line 425, in _error_catcher
    yield
  File "/storage/anaconda3/lib/python3.7/site-packages/urllib3/response.py", line 755, in read_chunked
    chunk = self._handle_chunk(amt)
  File "/storage/anaconda3/lib/python3.7/site-packages/urllib3/response.py", line 709, in _handle_chunk
    self._fp._safe_read(2)  # Toss the CRLF at the end of the chunk.
  File "/storage/anaconda3/lib/python3.7/http/client.py", line 612, in _safe_read
    raise IncompleteRead(b''.join(s), amt)
http.client.IncompleteRead: IncompleteRead(0 bytes read, 2 more expected)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/storage/anaconda3/lib/python3.7/site-packages/requests/models.py", line 750, in generate
    for chunk in self.raw.stream(chunk_size, decode_content=True):
  File "/storage/anaconda3/lib/python3.7/site-packages/urllib3/response.py", line 560, in stream
    for line in self.read_chunked(amt, decode_content=decode_content):
  File "/storage/anaconda3/lib/python3.7/site-packages/urllib3/response.py", line 781, in read_chunked
    self._original_response.close()
  File "/storage/anaconda3/lib/python3.7/contextlib.py", line 130, in __exit__
    self.gen.throw(type, value, traceback)
  File "/storage/anaconda3/lib/python3.7/site-packages/urllib3/response.py", line 443, in _error_catcher
    raise ProtocolError("Connection broken: %r" % e, e)
urllib3.exceptions.ProtocolError: ('Connection broken: IncompleteRead(0 bytes read, 2 more expected)', IncompleteRead(0 bytes read, 2 more expected))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    for chunk in r:
  File "/storage/anaconda3/lib/python3.7/site-packages/requests/models.py", line 753, in generate
    raise ChunkedEncodingError(e)
requests.exceptions.ChunkedEncodingError: ('Connection broken: IncompleteRead(0 bytes read, 2 more expected)', IncompleteRead(0 bytes read, 2 more expected))

Когда я открываю этот PDF-файл в веб-браузерах, таких как Google Chrome, встроенный плагин Chrome для PDF-файлов может загружать его правильно и его можно читать в браузере. Однако, если я пытаюсь загрузить его, нажав на значок загрузки, я получаю Failed - Network Error Firefox не может загрузить / загрузить его. (Оба Firefox и Chrome обновлены до последней версии) Когда я тестировал его на машине с Windows, Microsoft edge смогла загрузить PDF, хотя ...

Приведенный выше код, если я тестирую его с некоторыми другими PDF-файлами, такими каккак этот: https://adobe.com/content/dam/acom/en/accessibility/products/acrobat/pdfs/acrobat-x-accessibility-checker.pdf
Это работает отлично.

Я пробовал некоторые инструменты командной строки, такие как curl, wget, aria2c (с правильными заголовками, установленными как запрос браузера), все не смогли загрузитьpdf.

Вывод wget:

connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/pdf]
Saving to: ‘blah.pdf’

<pdf_url>     [      <=>                          ] 101.68K  66.1KB/s    in 1.5s    

2019-10-02 11:29:50 (69.1 KB/s) - Read error at byte 108786 (Success).

Файл, загруженный с помощью wget, поврежден.

Еще одна вещь, которую я пытался проверить, это использовать mitm икомбинация chromedriver + selenium.

Автоматический браузер Chrome не может загрузить PDF-файл и выдает ошибку:

502 Bad Gateway
HttpSyntaxException('Malformed chunked body',)

Как загрузить этот PDF-файл с помощью модуля requests? Буду очень признателен за любую помощь.

Ответы [ 2 ]

0 голосов
/ 08 октября 2019

Я выяснил проблему через пару дней. Сервер неправильно закрывал соединение, поэтому библиотеки python выдавали IncompleteReadError. Мне удалось скачать его, используя curl, установленный в системе с аргументом --compressed и всеми необходимыми заголовками:

from subprocess import call

pdf_url = ""
pdf_filename = ""
call(["curl", pdf_url, 
    '-H', 'Connection: keep-alive', 
    '-H', 'Cache-Control: max-age=0', 
    '-H', 'Upgrade-Insecure-Requests: 1', 
    '-H', 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', 
    '-H', 'Sec-Fetch-Mode: navigate', 
    '-H', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3', 
    '-H', 'Sec-Fetch-Site: cross-site', 
    '-H', 'Accept-Encoding: gzip, deflate, br', 
    '-H', 'Accept-Language: en-US,en;q=0.9,bn;q=0.8', 
    '-H', 'Cookie: bbb=rd102o00000000000000000000ffff978432aao80', 
    '--compressed', '--output', pdf_filename])

Используя вызов метода модуль подпроцесса . Несмотря на то, что curl показывает сообщение об ошибке, как показано ниже:

curl: (18) transfer closed with outstanding read data remaining

Но загруженный pdf-файл работает и может быть открыт любым просмотрщиком pdf.

0 голосов
/ 02 октября 2019

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

urllib.request.urlretrieve(url, 'foo_file.txt', data=your_queries)

Что делает метод urlretrieve, так это извлекает данные из ссылки и делает их копию в указанном вами имени файла и пути, который вы указываете в качестве второго аргумента. Вы также можете изменить тип на .pdf, .json, что угодно.

У вас есть больше информации здесь: https://docs.python.org/3.7/library/urllib.request.html#module-urllib.request

...