如何使用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或requests这样的额外库。这可能吗?
3 个回答
0
我也遇到过同样的问题。
我发现“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()
1
如果我没记错的话,下面这个方法之前对我有效:
data = ''
chunk = rsp.read()
while chunk:
data += chunk
chunk = rsp.read()
每次read
操作都会读取一小块数据,所以要一直读取,直到没有更多的数据可以读取为止。现在还没有相关的文档支持这个说法……
1
来自Python文档关于urllib2.urlopen的内容:
有一点需要注意:如果你在使用read()方法时没有指定读取的大小,或者指定了一个负数,那么它可能不会一直读取到数据流的末尾;在一般情况下,没有好的方法来判断从一个套接字(socket)中是否已经读取了整个数据流。
所以,建议在一个循环中读取数据:
req = urllib2.Request("https://myserver/mylargefile.gz")
rsp = urllib2.urlopen(req)
data = rsp.read(8192)
while data:
# .. Do Something ..
data = rsp.read(8192)