如何使用urllib3下载文件?

2024-04-08

这是基于该网站上的另一个问题:使用 urllib3 下载文件的最佳方式是什么 https://stackoverflow.com/questions/17285464/whats-the-best-way-to-download-file-using-urllib3但是,我不能在那里发表评论,所以我问另一个问题:

如何使用 urllib3 下载(更大的)文件?

我尝试使用与 urllib2 一起使用的相同代码(在Python 3中从网络下载文件 https://stackoverflow.com/questions/7243750/download-file-from-web-in-python-3),但 urllib3 失败:

http = urllib3.PoolManager()

with http.request('GET', url) as r, open(path, 'wb') as out_file:       
    #shutil.copyfileobj(r.data, out_file) # this writes a zero file
    shutil.copyfileobj(r.data, out_file)

这表示“bytes”对象没有属性“read”

然后我尝试使用该问题中的代码,但它陷入无限循环,因为数据始终为“0”:

http = urllib3.PoolManager()
r = http.request('GET', url)

with open(path, 'wb') as out:
    while True:
        data = r.read(4096)         
        if data is None:
            break
        out.write(data)
r.release_conn()

但是,如果我读取内存中的所有内容,文件就会正确下载:

http = urllib3.PoolManager()
r = http.request('GET', url)
with open(path, 'wb') as out:
    out.write(data)

我不想这样做,因为我可能会下载非常大的文件。 不幸的是,urllib 文档没有涵盖本主题中的最佳实践。

(另外,请不要建议使用 requests 或 urllib2,因为它们在自签名证书方面不够灵活。)


你已经非常接近了,所缺少的部分正在设置preload_content=False(这将是即将发布的版本中的默认设置)。您还可以将响应视为类似文件的对象,而不是.data属性(这是一个神奇的属性,希望有一天会被弃用)。

- with http.request('GET', url) ...
+ with http.request('GET', url, preload_content=False) ...

这段代码应该可以工作:

http = urllib3.PoolManager()

with http.request('GET', url, preload_content=False) as r, open(path, 'wb') as out_file:       
    shutil.copyfileobj(r, out_file)

urllib3 的响应对象也遵循io界面 https://docs.python.org/2/library/io.html,所以你也可以做类似的事情...

import io
response = http.request(..., preload_content=False)
buffered_response = io.BufferedReader(response, 2048)

只要你添加preload_content=False对于您的三种尝试中的任何一种并将响应视为类似文件的对象,它们都应该有效。

不幸的是,urllib 文档没有涵盖本主题中的最佳实践。

您完全正确,我希望您考虑通过在此处发送拉取请求来帮助我们记录此用例:https://github.com/shazow/urllib3 https://github.com/shazow/urllib3

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用urllib3下载文件? 的相关文章

随机推荐