我有一个小工具,我用来从一个网站上下载一个MP3文件,然后构建/更新一个播客XML文件,我已经添加到iTunes。

创建/更新XML文件的文本处理是用Python编写的。但是,我在Windows .bat文件中使用wget来下载实际的MP3文件。我更喜欢用Python编写整个实用程序。

我努力寻找一种用Python实际下载该文件的方法,因此我使用了wget。

那么,如何使用Python下载文件呢?


当前回答

我写了下面的代码,它可以在普通的Python 2或Python 3中工作。


import sys
try:
    import urllib.request
    python3 = True
except ImportError:
    import urllib2
    python3 = False


def progress_callback_simple(downloaded,total):
    sys.stdout.write(
        "\r" +
        (len(str(total))-len(str(downloaded)))*" " + str(downloaded) + "/%d"%total +
        " [%3.2f%%]"%(100.0*float(downloaded)/float(total))
    )
    sys.stdout.flush()

def download(srcurl, dstfilepath, progress_callback=None, block_size=8192):
    def _download_helper(response, out_file, file_size):
        if progress_callback!=None: progress_callback(0,file_size)
        if block_size == None:
            buffer = response.read()
            out_file.write(buffer)

            if progress_callback!=None: progress_callback(file_size,file_size)
        else:
            file_size_dl = 0
            while True:
                buffer = response.read(block_size)
                if not buffer: break

                file_size_dl += len(buffer)
                out_file.write(buffer)

                if progress_callback!=None: progress_callback(file_size_dl,file_size)
    with open(dstfilepath,"wb") as out_file:
        if python3:
            with urllib.request.urlopen(srcurl) as response:
                file_size = int(response.getheader("Content-Length"))
                _download_helper(response,out_file,file_size)
        else:
            response = urllib2.urlopen(srcurl)
            meta = response.info()
            file_size = int(meta.getheaders("Content-Length")[0])
            _download_helper(response,out_file,file_size)

import traceback
try:
    download(
        "https://geometrian.com/data/programming/projects/glLib/glLib%20Reloaded%200.5.9/0.5.9.zip",
        "output.zip",
        progress_callback_simple
    )
except:
    traceback.print_exc()
    input()

注:

支持“进度条”回调。 从我的网站上下载一个4 MB的测试包。zip。

其他回答

2012年,使用python请求库

>>> import requests
>>> 
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760

您可以运行pip install请求来获取它。

请求比替代方法有很多优点,因为API简单得多。如果必须进行身份验证,则尤其如此。Urllib和urllib2在这种情况下非常不直观和痛苦。


2015-12-30

人们对进度条表示钦佩。这当然很酷。现在有几种现成的解决方案,包括tqdm:

from tqdm import tqdm
import requests

url = "http://download.thinkbroadband.com/10MB.zip"
response = requests.get(url, stream=True)

with open("10MB", "wb") as handle:
    for data in tqdm(response.iter_content()):
        handle.write(data)

这实际上是@kvance在30个月前描述的实现。

还有一个,使用urlretrieve:

import urllib.request
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

(对于Python 2使用import urllib和urllib.urlretrieve)

为了完整起见,还可以使用子流程包调用任何程序来检索文件。专用于检索文件的程序比Python函数(如urlretrieve)更强大。例如,wget可以递归下载目录(-R),可以处理FTP、重定向、HTTP代理,可以避免重新下载现有文件(-nc),而aria2可以进行多连接下载,这可能会加快下载速度。

import subprocess
subprocess.check_output(['wget', '-O', 'example_output_file.html', 'https://example.com'])

在Jupyter Notebook中,也可以直接使用!语法:

!wget -O example_output_file.html https://example.com

Urlretrieve和请求。得到的都很简单,然而现实却不。 我已经为两个站点提取了数据,包括文本和图像,以上两个可能解决了大部分任务。但如果想要更通用的解决方案,我建议使用urlopen。由于它包含在Python 3标准库中,您的代码可以在任何运行Python 3的机器上运行,而无需预先安装site-package

import urllib.request
url_request = urllib.request.Request(url, headers=headers)
url_connect = urllib.request.urlopen(url_request)

#remember to open file in bytes mode
with open(filename, 'wb') as f:
    while True:
        buffer = url_connect.read(buffer_size)
        if not buffer: break

        #an integer value of size of written data
        data_wrote = f.write(buffer)

#you could probably use with-open-as manner
url_connect.close()

当使用Python通过HTTP下载文件时,这个答案提供了HTTP 403禁止的解决方案。我只尝试了请求和urllib模块,其他模块可能会提供更好的东西,但这是我用来解决大多数问题的一个。

在python3中,可以使用urllib3和shutil库。 使用pip或pip3下载它们(取决于python3是否默认)

pip3 install urllib3 shutil

然后运行这段代码

import urllib.request
import shutil

url = "http://www.somewebsite.com/something.pdf"
output_file = "save_this_name.pdf"
with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)

注意,您下载了urllib3,但在代码中使用了urllib