Как загрузить фрагментированные данные с помощью Python urllib2

Я пытаюсь загрузить большой файл с сервера с Python 2:

req = urllib2.Request("https://myserver/mylargefile.gz")
rsp = urllib2.urlopen(req)
data = rsp.read()

Сервер отправляет данные с «Transfer-Encoding: chunked», и я получаю только некоторые двоичные данные, которые не могут быть распакованы gunzip.

Должен ли я перебирать несколько read()? Или несколько запросов? Если да, то как они должны выглядеть?

Примечание. Я пытаюсь решить проблему только со стандартной библиотекой Python 2, без дополнительных библиотек, таких как urllib3 или запросы. Это вообще возможно?


person Community    schedule 24.06.2014    source источник


Ответы (3)


Из документации по python на urllib2.urlopen:

Одно предостережение: метод read(), если аргумент размера опущен или отрицателен, может не читаться до конца потока данных; в общем случае нет хорошего способа определить, что весь поток из сокета был прочитан.

Итак, читаем данные в цикле:

req = urllib2.Request("https://myserver/mylargefile.gz")
rsp = urllib2.urlopen(req)
data = rsp.read(8192)
while data:
   # .. Do Something ..
   data = rsp.read(8192)
person jaime    schedule 24.06.2014
comment
У меня сложилось впечатление, что это работает для загрузки только файлов, которые не отправляются с параметром transfer-encoding=chunked. - person ; 24.06.2014
comment
Хм, ты прав. Я видел аналогичный вопрос без ответа: stackoverflow.com/ вопросов/15115606/ Извините, я не знаю, как это обойти. Единственный ответ использовал curl. - person jaime; 24.06.2014
comment
Хорошо, я попробую curl, который немного громоздкий с файлами cookie для входа по сравнению с Python, но лучше, чем ничего. Спасибо! - person ; 24.06.2014

Если я не ошибаюсь, у меня некоторое время назад работало следующее:

data = ''
chunk = rsp.read()
while chunk:
    data += chunk
    chunk = rsp.read()

Каждый read читает один фрагмент - так что продолжайте читать, пока ничего больше не появится. У вас нет готовой документации, подтверждающей это... пока.

person sebastian    schedule 24.06.2014
comment
К сожалению, у меня это не работает: content = '' while True: chunk = rsp.read(), если не чанк разрыв содержимого += чанка f.write(content) - person ; 24.06.2014
comment
does not work к сожалению, это очень бесполезное утверждение :) Не хватает контента? - person sebastian; 25.06.2014
comment
Извините: не работает в смысле ровно как раньше. т.е. данные не полные и не могут быть прочитаны gunzip. Я предполагаю, что urllib2 просто не поддерживает кодирование передачи по частям. - person ; 25.06.2014

У меня та же проблема.

Я обнаружил, что «Transfer-Encoding: chunked» часто появляется вместе с «Content-Encoding: gzip».

Так что, возможно, мы сможем получить сжатый контент и разархивировать его.

Меня устраивает.

import urllib2
from StringIO import StringIO
import gzip

req = urllib2.Request(url)
req.add_header('Accept-encoding', 'gzip, deflate')
rsp = urllib2.urlopen(req)
if rsp.info().get('Content-Encoding') == 'gzip':
    buf = StringIO(rsp.read())
    f = gzip.GzipFile(fileobj=buf)
    data = f.read()
person Mengtian.Wang    schedule 24.10.2019