在本教程中,我们将学习到使用不同的Python模块从网页上下载文件,包括常规文件,网页和其它来源。
我们会在其中遇到各种可能的挑战,比如下载重定向,大文件下载,多线程下载等。
请来看本文。
使用 Requests
从某个网址下载文件可以使用 requests 模块。
请看如下代码:
import requests
url = 'https://www.python.org/static/img/python-logo@2x.png'
myfile = requests.get(url)
open('c:/users/21cto/downloads/PythonImage.png', 'wb').write(myfile.content)
只需要使用request模块的get方法获取URL,接着将结果存储到myfile变量中即可,最后将变量的内容写入到文件。
使用 wget
还可以使用 wget 模块来从URL上下载文件,它也是Python的标准模块,如果没有安装,使用pip命令开始安装:
pip install wget
如下代码,我们将下载Python的logo和相关图片:
import wget
url = "python-logo@2x.png"" rel="nofollow" target="_blank">https://www.python.org/static/ ... ot%3B
wget.download(url, 'c:/users/LikeGeeks/downloads/pythonLogo.png')
在以上代码中,URL和图片的全路径会传递到wget模块的download方法,最后文件如果存在就会下载到目的路径和文件存储。
下载重定向文件
在本节中,我们将学习到从URL下载,该URL将请求会重定向到另一个URL中,比如如下URL:
https://readthedocs.org/projec ... test/
想要下载该pdf文件,我们使用如下代码:
import requests
url = 'https://readthedocs.org/projects/python-guide/downloads/pdf/latest/'
myfile = requests.get(url, allow_redirects=True)
open('c:/users/21cto/documents/PythonBook.pdf', 'wb').write(myfile.content)
在以上代码中,我们第一步是指定URL,然后使用requests模块的get方法来获取URL内容。在get方法中,需要设置allow_redirects为True,也就是允许URL重定向,然后将重定向的内容分配给myfile变量。
最后,打开一个文件用来写入获取到的内容,完成下载。
下载大尺寸文件
请看如下代码:
import requests
url = 'https://www.python.org/static/img/python-logo@2x.png'
myfile = requests.get(url)
open('c:/users/21cto/downloads/PythonImage.png', 'wb').write(myfile.content)
第一步,我们和前面一样使用requests模块的get方法,但是在此处,需要把stream属性设置为True。接下来,在当前工作目录中创建一个名叫PythonBook.pdf的文件,打开并开始写入。
接下来指定一次要下载的块尺寸,我们将其设置为1024字节,然后遍历每个块,接着把这些块写入文件中,直接块全部写完为止。
貌似不是很好看?不有担心,一会我们使用显示进度条的下载方式。
下载多个文件(并行/批量下载)
如果要一次下载多个文件,需要导入如下模块:
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)
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)
运行该脚本即可。
下载显示进度条
Python中的进度条是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循环,在把内容写入文件时,我们使用了progress模块的bar方法。
使用urllib下载
我们也可以使用urllib来下载网页。urllib库是Python的标准库,不需要额外再安装。
可以用如下代码来下载URL资源:urllib.request.urlretrieve('url', 'path')
接下来要指定要保存的路径,如下:urllib.request.urlretrieve('https://www.python.org/', 'c:/users/21cto/documents/PythonOrganization.html')
在此段代码中,使用urlretrieve方法,传给了源下载文件的网址以及文件存储的路径,扩展名为.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方法打开代理服务器,传递代理对象。
接着,开始发起检索页面之请求。
另外,还可以使用Python官方文档中的requests模块来运行。代码如下:
import requests
myProxy = { 'http': 'http://127.0.0.2:3001' }
requests.get("https://www.python.org/", proxies=myProxy)
只需导入requests模块,创建自己的代理对象,就可以下载文件了。
使用urllib3
urllib3是urllib模块的改进版本。需要使用pip下载并安装它:pip install urllib3
接下来下载一个网页,使用urllib3来把它存储在文本文件中。import urllib3, shutil
shutil是用来处理文件时使用。接下来,初始化URL字符串变量:url = 'https://www.python.org/'
接下来,使用PoolManager来跟踪相关的连接池。c = urllib3.PoolManager()
接下来,创建一个文件。filename = "mytest.txt"
最后,使用GET方式来请求并获取URL内容,接下来打开文件,将返回的响应写入该文件中。代码如下:
with c.request('GET', url, preload_content=False) as res, open(filename, 'wb') as out_file:
shutil.copyfileobj(res, out_file)
异步下载
asyncio模块专门用来处理系统事件,它围绕着事件循环来工作,循环等待,事件发生,然后对该事件进行反应,该反应可能是调用另一个函数。
asyncio模块使用协程进行事件处理。
接下来使用asyncio事件处理和协程功能,导入asyncio模块:import asyncio
接下来,定义异步协程之方法:async def coroutine():
await my_func()
这里给大家说明一下,关键字asyncz表示是一个本地asyncio协程。在协程主体内部,有await关键字,此关键字返回某值,亦可以使用return关键字。
现在,我们使用协程来创建一段完整代码,从Python官方网站下载文件:
>>> import os
>>> import urllib.request
>>> async def coroutine(url):
r = urllib.request.urlopen(url)
filename = "couroutine_downloads.txt"
with open(filename, 'wb') as f:
for ch in r:
f.write(ch)
print_msg = '下载已经成功'
return print_msg
>>> async def main_func(urls_to_download):
co = [coroutine(url) for url in urls_to_download]
downloaded, downloading = await asyncio.wait(co)
for i in downloaded:
print(i.result())
urls_to_download = ["https://www.python.org/events/ ... ot%3B,
"https://www.python.org/events/ ... ot%3B,
"https://www.python.org/events/ ... ot%3B,
"https://www.python.org/events/ ... ot%3B]
>>> eventLoop = asyncio.get_event_loop()
>>> eventLoop.run_until_complete(main_func(urls_to_download))
在上面的Python代码中,我们创建了一个异步协程函数,该函数下载文件后会返回一条消息,接下来有另一个异步协程调用,main_fun形成队列,asyncio等待功能完成后,协程结束。
如果要启动协程,需要使用asyncio的get_event_loop()方法把协程放入事件循环中,最后用run_until_complete()执行事件循环。
使用Pyton下载文件非常有趣,多磨练,会有更多有益的东西。希望本教程对大家有帮助!
作者:新楚