Python中基本的HTTP文件下载和保存到磁盘的方法是什么?

202

我浏览了这个网站上的问答,寻找一个回答我的问题的答案。但是,我是初学者,我发现有些解决方案很难理解。我需要一个非常基本的解决方案。

请问有人能够向我简单解释如何“通过http下载文件”并将其“保存到Windows磁盘”吗?

我也不确定如何使用shutil和os模块。

我要下载的文件不到500 MB,是一个.gz归档文件。如果有人能够解释如何提取该归档文件并利用其中的文件,那就太好了!

以下是我从不同答案中结合起来写的部分解决方案:

import requests
import os
import shutil

global dump

def download_file():
    global dump
    url = "http://randomsite.com/file.gz"
    file = requests.get(url, stream=True)
    dump = file.raw

def save_file():
    global dump
    location = os.path.abspath("D:\folder\file.gz")
    with open("file.gz", 'wb') as location:
        shutil.copyfileobj(dump, location)
    del dump

有人能指出错误(初学者级别),并解释一下更简单的方法吗?


请注意,如果您从PyCharm下载,请注意“当前文件夹”在哪里。 - Charlie Parker
10个回答

229

下载文件的清晰方式是:

import urllib

testfile = urllib.URLopener()
testfile.retrieve("http://randomsite.com/file.gz", "file.gz")

这个操作会从网站下载一个文件并将其命名为file.gz。这是我最喜欢的解决方案之一,来自使用urllib和Python下载图片

这个例子使用了urllib库,可以直接从源中检索文件。


3
好的,谢谢!但是有没有通过requests使它正常工作的方法? - arvindch
5
能否将 /myfolder/file.gz 文件保存起来? - John Lapoya
18
也许自己尝试一下是没有比这更好的可能性了吧? :) 我可以成功地执行testfile.retrieve("http://example.com/example.rpm", "/tmp/test.rpm") - Dharmit
32
自Python 3.3起,此方法已被弃用,urllib.request.urlretrieve解决方案(请参见下面的答案)是“现代”方法。 - MichielB
1
如何在这段代码中添加用户名和密码是最佳方式?谢谢。 - Estefy
显示剩余6条评论

191

对于Python3+,URLopener已经被弃用。当你使用它时,你会得到以下错误:

url_opener = urllib.URLopener() AttributeError: module 'urllib' has no attribute 'URLopener'

因此,请尝试:

import urllib.request 
urllib.request.urlretrieve(url, filename)

10
奇怪,为什么没有人投票支持这个答案,当Python 2已经被弃用且只有这个解决方案能正常工作时... - wowkin2
3
同意!之前的解决方案让我抓狂了。但愿我能投200个赞! - Yechiel K
1
如何指定要将URL内容保存到哪个文件夹/路径? - Charlie Parker
1
请注意,如果您从PyCharm下载,请注意“当前文件夹”在哪里。 - Charlie Parker
你应该得到更多的点赞。我不明白为什么 Python 2 的解决方案仍然被接受。 - Fernando Ortega

120

正如这里所提到的:

import urllib
urllib.urlretrieve ("http://randomsite.com/file.gz", "file.gz")

编辑: 如果您仍然想使用requests,请查看这个问题这一个


2
urllib可以工作,但是许多人似乎推荐使用requests而不是urllib。为什么呢? - arvindch
2
当使用REST API时,与urllib相比,requests非常有帮助。除非您想要做更多的事情,否则使用它就足够了。 - dparpyani
好的,现在我已经阅读了您提供的有关请求使用的链接。我对如何声明文件路径以保存下载感到困惑。我该如何使用os和shutil来实现呢? - arvindch
83
对于Python3:import urllib.request urllib.request.urlretrieve(url, filename) - Flash
1
如果下载失败,我无法提取HTTP状态码。 - Aashish Thite
显示剩余4条评论

43

使用wget、urllib和request的四种方法。

#!/usr/bin/python
import requests
from StringIO import StringIO
from PIL import Image
import profile as profile
import urllib
import wget


url = 'https://tinypng.com/images/social/website.jpg'

def testRequest():
    image_name = 'test1.jpg'
    r = requests.get(url, stream=True)
    with open(image_name, 'wb') as f:
        for chunk in r.iter_content():
            f.write(chunk)

def testRequest2():
    image_name = 'test2.jpg'
    r = requests.get(url)
    i = Image.open(StringIO(r.content))
    i.save(image_name)

def testUrllib():
    image_name = 'test3.jpg'
    testfile = urllib.URLopener()
    testfile.retrieve(url, image_name)

def testwget():
    image_name = 'test4.jpg'
    wget.download(url, image_name)

if __name__ == '__main__':
    profile.run('testRequest()')
    profile.run('testRequest2()')
    profile.run('testUrllib()')
    profile.run('testwget()')

testRequest - 在20.236秒内进行了4469882次函数调用(其中4469842次为原始调用)

testRequest2 - 在0.072秒内进行了8580次函数调用(其中8574次为原始调用)

testUrllib - 在0.036秒内进行了3810次函数调用(其中3775次为原始调用)

testwget - 在0.020秒内进行了3489次函数调用


1
你是如何得到函数调用次数的? - Abdelhak

38

我使用 wget

如果您需要例子,这是一个简单且好用的库。

import wget

file_url = 'http://johndoe.com/download.zip'

file_name = wget.download(file_url)

wget模块支持Python 2和Python 3版本


6

异国情调的Windows解决方案

import subprocess

subprocess.run("powershell Invoke-WebRequest {} -OutFile {}".format(your_url, filename), shell=True)

6
import urllib.request
urllib.request.urlretrieve("https://raw.githubusercontent.com/dnishimoto/python-deep-learning/master/list%20iterators%20and%20generators.ipynb", "test.ipynb")

下载单个未经处理的Jupyter笔记本到文件。


3

对于文本文件,您可以使用:

import requests

url = 'https://WEBSITE.com'
req = requests.get(url)
path = "C:\\YOUR\\FILE.html"

with open(path, 'wb') as f:
    f.write(req.content)

难道你不需要使用req.iter_content()吗?或者使用req.raw文件对象?请参见这里 - Michael Schnerring
不,它就是工作的,你试过了吗?@MichaelSchnerring - DaWe

2

我开始走这条路,是因为ESXi的wget没有编译SSL,我想直接从供应商的网站下载OVA到位于世界另一端的ESXi主机。

我不得不通过编辑规则来禁用防火墙(懒),并启用https输出(正确)。

创建了Python脚本:

import ssl
import shutil
import tempfile
import urllib.request
context = ssl._create_unverified_context()

dlurl='https://somesite/path/whatever'
with urllib.request.urlopen(durl, context=context) as response:
    with open("file.ova", 'wb') as tmp_file:
        shutil.copyfileobj(response, tmp_file)

ESXi库有点简化,但开源的weasel安装程序似乎使用urllib来处理https...所以这启发我走上了这条路


-6

另一种干净的保存文件的方法是这样的:

import csv
import urllib

urllib.retrieve("your url goes here" , "output.csv")

这可能应该是 urllib.urlretrieveurllib.URLopener().retrieve,不确定你在这里指的是哪一个。 - mateor
12
如果你只是要给文件命名,为什么要导入CSV文件? - Azeezah M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接