在本教程中,您将学习如何使用不同的 Python 模块从网络下载文件。您将下载常规文件、网页、Amazon S3 和其他源。
此外,您还将学习如何克服您可能遇到的许多挑战,例如下载重定向文件、下载大文件、多线程下载和其他策略。
使用请求
您可以使用 requests 模块从 URL 下载文件。
考虑下面的代码:
import requests
url = 'https://www.python.org/static/img/python-logo@2x.png'
myfile = requests.get(url)
open('c:/users/LikeGeeks/downloads/PythonImage.png', 'wb').write(myfile.content)
简单地说,使用 requests 模块的 get 方法获取 URL,并将结果存储到变量“myfile”变量中。然后将变量的内容写入文件中。
使用 wget
您还可以使用以下命令从 URL 下载文件wgetPython 的模块。使用 pip 安装 wget 模块,如下所示:
pip install wget
考虑以下代码,我们将在其中下载 Python 的徽标图像:
import wget
url = "https://www.python.org/static/img/python-logo@2x.png"
wget.download(url, 'c:/users/LikeGeeks/downloads/pythonLogo.png')
在此代码中,我们将 URL 以及路径(存储图像的位置)传递给 wget 模块的 download 方法。
下载重定向的文件
在本节中,您将学习使用请求从重定向到另一个包含 .pdf 文件的 URL 进行下载。网址如下:
https://readthedocs.org/projects/python-guide/downloads/pdf/latest/
要下载此 pdf 文件,请使用以下代码:
import requests
url = 'https://readthedocs.org/projects/python-guide/downloads/pdf/latest/'
myfile = requests.get(url, allow_redirects=True)
open('c:/users/LikeGeeks/documents/hello.pdf', 'wb').write(myfile.content)
在此代码中,第一步我们指定 URL。然后我们使用requests模块的get方法来获取URL。在 get 方法中,我们设置允许重定向设置为 True,这将允许 URL 中的重定向。重定向后,内容将位于myfile多变的。
最后,我们打开一个文件来写入获取的内容。
分块下载大文件
考虑一下崩溃的代码:
import requests
url = 'https://www.cs.uky.edu/~keen/115/Haltermanpythonbook.pdf'
r = requests.get(url, stream = True)
with open("PythonBook.pdf", "wb") as Pypdf:
for chunk in r.iter_content(chunk_size = 1024):
if chunk:
Pypdf.write(chunk)
首先,我们像之前一样使用requests模块的get方法,但是这次我们将stream属性设置为True。
然后我们在当前工作目录中创建一个名为PythonBook.pdf的文件并打开它进行写入。
然后我们指定一次要下载的块大小。我们设置为 1024 字节。迭代每个块并将块写入文件中,直到块完成。
下载块时,Python shell 将如下所示:
不漂亮?不用担心;稍后我们将显示下载过程的进度条。
下载多个文件(并行/批量下载)
要一次下载多个文件,请导入以下模块:
import os
import requests
from time import time
from multiprocessing.pool import ThreadPool
我们导入了 os 和 time 模块来检查下载文件需要多少时间。 ThreadPool 模块允许您使用池运行多个线程或进程。
让我们创建一个简单的函数,它将响应分块发送到文件:
def url_response(url):
path, url = url
r = requests.get(url, stream = True)
with open(path, 'wb') as f:
for ch in r:
f.write(ch)
URLs 变量是一个二维数组,指定要下载的页面的路径和 URL。
urls = [("Event1", "https://www.python.org/events/python-events/805/"),
("Event2", "https://www.python.org/events/python-events/801/"),
("Event3", "https://www.python.org/events/python-events/790/"),
("Event4", "https://www.python.org/events/python-events/798/"),
("Event5", "https://www.python.org/events/python-events/807/"),
("Event6", "https://www.python.org/events/python-events/807/"),
("Event7", "https://www.python.org/events/python-events/757/"),
("Event8", "https://www.python.org/events/python-user-group/816/")]
将 URL 传递给 requests.get,就像我们在上一节中所做的那样。最后,打开文件(URL中指定的路径)并写入页面内容。
现在我们可以为每个 URL 单独调用这个函数,也可以同时为所有 URL 调用这个函数。让我们在 for 循环中分别对每个 URL 执行此操作,并注意计时器:
start = time()
for x in urls:
url_response (x)
print(f"Time to download: {time() - start}")
结果会是这样的:
现在用以下代码行替换 for 循环:
ThreadPool(9).imap_unordered(url_response, urls)
运行脚本:
下载有进度条
进度条是 clint 模块的 UI 小部件。要安装 clint 模块,请键入以下命令:
pip install clint
考虑以下代码:
import requests
from clint.textui import progress
url = 'http://do1.dr-chuck.com/pythonlearn/EN_us/pythonlearn.pdf'
r = requests.get(url, stream=True)
with open("LearnPython.pdf", "wb") as Pypdf:
total_length = int(r.headers.get('content-length'))
for ch in progress.bar(r.iter_content(chunk_size = 2391975), expected_size=(total_length/1024) + 1):
if ch:
Pypdf.write(ch)
在此代码中,我们导入了 requests 模块,然后从 clint.textui 导入了进度小部件。唯一的区别在于 for 循环。我们在将内容写入文件时使用了进度模块的 bar 方法。输出将如下所示:
使用 urllib 下载网页
在本节中,我们将使用 urllib 下载网页。
urllib库是Python的标准库,因此不需要安装它。
下面这行代码可以轻松下载一个网页:
urllib.request.urlretrieve('url', 'path')
在此处指定您要另存为的 URL 以及存储位置:
urllib.request.urlretrieve('https://www.python.org/', 'c:/users/LikeGeeks/documents/PythonOrganization.html')
在此代码中,我们使用 urlretrieve 方法并传递文件的 URL 以及保存文件的路径。文件扩展名为 .html。
通过代理下载
如果需要使用代理下载文件,可以使用 urllib 模块的 ProxyHandler。检查以下代码:
>>> import urllib.request
>>> myProxy = urllib.request.ProxyHandler({'http': '127.0.0.2'})
>>> openProxy = urllib.request.build_opener(myProxy)
>>> urllib.request.urlretrieve('https://www.python.org/')
在这段代码中,我们创建了代理对象,并通过调用urllib的build_opener方法打开代理并传递代理对象。然后我们发出检索页面的请求。
此外,您可以使用官方文档中记录的 requests 模块:
import requests
myProxy = { 'http': 'http://127.0.0.2:3001' }
requests.get("https://www.python.org/", proxies=myProxy)
只需导入请求模块并创建代理对象即可。然后您就可以检索该文件。
使用 urllib3
urllib3 是 urllib 模块的改进版本。您可以使用 pip 下载并安装它:
pip install urllib3
我们将使用 urllib3 获取网页并将其存储在文本文件中。
导入以下模块:
import urllib3, shutil
处理文件时可以使用 Shutil 模块。现在像这样初始化 URL 字符串变量:
url = 'https://www.python.org/'
然后我们使用 urllib3 的 PoolManager 来跟踪必要的连接池。
c = urllib3.PoolManager()
创建一个文件:
filename = "test.txt"
最后,我们发送一个 GET 请求来获取 URL 并打开一个文件并将响应写入该文件:
with c.request('GET', url, preload_content=False) as res, open(filename, 'wb') as out_file:
shutil.copyfileobj(res, out_file)
使用 boto3 从 S3 下载文件
要从 Amazon S3 下载文件,您可以使用 Python boto3 模块。
首先,您需要使用 pip 安装 awscli 模块:
pip install awscli
对于 AWS 配置,请运行以下命令:
aws configure
现在输入您的详细信息:
AWS Access Key ID [None]: (The access key)
AWS Secret Access Key [None]: (Secret access key)
Default region name [None]: (Region)
Default output format [None]: (Json)
要从 Amazon S3 下载文件,请导入 boto3 和 botocore。 Boto3 是一个适用于 Python 的 Amazon SDK,用于访问 S3 等 Amazon Web 服务。 Botocore 提供命令行服务来与 Amazon Web 服务交互。
Botocore 附带 awscli。要安装 boto3,请运行以下命令:
pip install boto3
现在导入这两个模块:
import boto3, botocore
从亚马逊下载文件时,我们需要三个参数:
- 桶的名称
- 您需要下载的文件的名称
- 下载后的文件名称
初始化变量:
bucket = "bucketName"
file_name = "filename"
downloaded_file = "downloadedfilename"
现在初始化一个变量以使用会话的资源。为此,我们将调用 boto3 的 resources() 方法并传递 s3 服务:
service = boto3.resource(‘s3’)
最后,使用 download_file 方法下载文件并传入变量:
service.Bucket(bucket).download_file(file_name, downloaded_file)
使用异步
您可以使用 asyncio 模块来处理系统事件。它围绕事件循环工作,等待事件发生然后对该事件做出反应。反应可以是调用另一个函数。这个过程称为事件处理。 asyncio 模块使用协程进行事件处理。
要使用 asyncio 事件处理和协程功能,我们将导入 asyncio 模块:
import asyncio
另外,我们需要安装 aiohttp 模块。
pip install aiohttp
我们将导入 async_timeout 模块来处理超时。
import async_timeout
关键字 async 表明这是一个原生 asyncio 协程。在协程的主体内部,我们有await关键字,它返回一个特定的值。我们还使用了 return 关键字。
现在让我们创建一个使用协程从网络下载文件的代码:
import asyncio
import uuid
import aiohttp
import async_timeout
async def get_url(url, session):
file_name = str(uuid.uuid4())
async with async_timeout.timeout(120):
async with session.get(url) as response:
with open(file_name, 'wb') as fd:
async for data in response.content.iter_chunked(1024):
fd.write(data)
return 'Successfully downloaded ' + file_name
async def main(urls):
async with aiohttp.ClientSession() as session:
tasks = [get_url(url, session) for url in urls]
return await asyncio.gather(*tasks)
urls = ["https://www.python.org/events/python-events/801/",
"https://www.python.org/events/python-events/790/",
"https://www.python.org/events/python-user-group/816/",
"https://www.python.org/events/python-events/757/"]
loop = asyncio.get_event_loop()
results = loop.run_until_complete(main(urls))
print('\n'.join(results))
在此代码中,我们创建了一个异步协程函数,该函数以块的形式下载文件并使用随机文件名保存它们并返回一条消息。
然后,我们有另一个异步协程调用 get_url 并等待 URL 并创建所有 URL 的队列。
现在要启动协程,我们必须使用 asyncio 的 get_event_loop() 方法将协程放入事件循环中,最后使用 asyncio 的 run_until_complete() 方法执行事件循环。
使用 Python 下载文件很有趣。我希望您觉得本教程有用。
谢谢。