python单击url下载网页文件_Python实现web文件(常规url、重定向url)下载方式总结

web-download.png

简介

Python提供了多种下载web文件(pdf、文档、图片和视频等)的方式,在本文中将介绍以下要点:

下载常规文件;

下载重定向文件;

下载大型文件;

多线程下载。

requests方法

requests 模块提供了简单的方式实现url链接文件的下载。

比如以下代码:

import requests

url = 'https://www.python.org/static/img/python-logo@2x.png'

file = requests.get(url)

with open('logo.png', 'wb') as f:

f.write(file.content)

1

2

3

4

5

6

importrequests

url='https://www.python.org/static/img/python-logo@2x.png'

file=requests.get(url)

withopen('logo.png','wb')asf:

f.write(file.content)

在这里我们下载Python官网的logo图片。首先导入

requests 模块,调用

get 方法下载url的响应头,连接保持打开状态,并将结果保存到变量

file 中,最后通过

file.content 将内容写入文件方法,将内容保存到当前目录,并命名为logo.png。

wget方法

熟悉Linux命令的都对

wget 不陌生,Python同样提供了

wget 模块,能够通过url很方便地下载文件。

代码如下:

import wget

url = 'https://www.python.org/static/img/python-logo@2x.png'

wget.download(url, './logo.png')

1

2

3

4

importwget

url='https://www.python.org/static/img/python-logo@2x.png'

wget.download(url,'./logo.png')

同样是下载Python官网的logo文件。在这段代码中,url和本地保存的地址直接传递给

wget.download 方法。需要注意的是

wget 本身不在

anaconda 中,需要使用

pipinstallwget 下载安装。

重定向文件下载

在下载一个文件时, 通过url链接常常不能直接访问文件url,web服务器会经过重定向方式引导到真正的链接地址,Python提供了适合重定向的链接下载方式。

代码如下:

import requests

url = 'https://readthedocs.org/projects/python-guide/downloads/pdf/latest/'

file = requests.get(url, allow_redirects=True)

with open('finthon.pdf', 'wb') as f:

f.write(file.content)

1

2

3

4

5

6

importrequests

url='https://readthedocs.org/projects/python-guide/downloads/pdf/latest/'

file=requests.get(url,allow_redirects=True)

withopen('finthon.pdf','wb')asf:

f.write(file.content)

在这里,我们同样使用

requests 模块的

get 方法获取该url的内容,在

get 方法中传入

allow_redirects=True 参数,允许重定向操作,并将重定向后的内容传给变量

file ,最后保存文件到finthon.pdf。

大文件分块下载

默认情况下,

requests 当你进行网络请求后,响应体会立即被下载,当数据过大时会导致内存不足。当在请求上设置

stream=True 时,这避免了立即将内容读入内存以获得较大的响应。推迟下载响应体直到访问

Response.content  属性。如果

stream=False (默认),数据将作为单个块返回。

代码如下:

import requests

url = 'https://www.python.org/static/img/python-logo@2x.png'

with open('logo.png', 'wb') as f:

with requests.get(url, stream=True) as r:

for chunk in r.iter_content(chunk_size=20):

if chunk:

f.write(chunk)

1

2

3

4

5

6

7

8

importrequests

url='https://www.python.org/static/img/python-logo@2x.png'

withopen('logo.png','wb')asf:

withrequests.get(url,stream=True)asr:

forchunkinr.iter_content(chunk_size=20):

ifchunk:

f.write(chunk)

如果你在请求中

stream=True ,

Requests 无法将连接释放回连接池,除非你消耗了所有的数据,或者调用了

Response.close 。 这样会带来连接效率低下的问题。如果你发现你在使用

stream=True 的同时还在部分读取请求的 body(或者完全没有读取 body),那么你就应该考虑使用 with 语句发送请求,这样可以保证请求一定会被关闭。

在这里

chunk_size 控制每次读取大小为20字节的块,当所有的块都读完后,保存到logo.png文件中。

并行批量下载多个文件

import requests

from time import time

from multiprocessing.pool import ThreadPool

1

2

3

importrequests

fromtimeimporttime

frommultiprocessing.poolimportThreadPool

我们导入了

time 模块来检查下载文件需要多少时间。

ThreadPool 模块允许你使用池运行多个线程或进程。

首先创建一个简单的函数,将响应分块发送到一个文件:

def get_url(url, name):

with open(name, 'wb') as f:

with requests.get(url, stream=True) as r:

for chunk in r.iter_content(chunk_size=20):

if chunk:

f.write(chunk)

1

2

3

4

5

6

defget_url(url,name):

withopen(name,'wb')asf:

withrequests.get(url,stream=True)asr:

forchunkinr.iter_content(chunk_size=20):

ifchunk:

f.write(chunk)

接下来我们要批量下载多个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-events/816')]

1

2

3

4

5

6

7

8

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-events/816')]

我们将这些url传递给

requests.get 。最后,我们打开文件(url中指定的路径)并写入页面内容。

现在,我们可以分别为每个url调用这个函数,我们也可以同时为所有url调用这个函数。让我们在for循环中分别为每个url调用这个函数,注意计时器:

start = time()

for x in urls:

get_url(x[1], x[0])

end = time()

print('time to download: ', end - start)

1

2

3

4

5

start=time()

forxinurls:

get_url(x[1],x[0])

end=time()

print('time to download: ',end-start)

输出:

time to download: 10.102667570114136

1

timetodownload:10.102667570114136

现在,考虑以下代码:

p = ThreadPool(8)

start = time()

for x in urls:

p.apply_async(get_url, args=(x[1], x[0]))

p.close()

p.join() #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束

end = time()

print('time to download: ', end - start)

1

2

3

4

5

6

7

8

p=ThreadPool(8)

start=time()

forxinurls:

p.apply_async(get_url,args=(x[1],x[0]))

p.close()

p.join()#调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束

end=time()

print('time to download: ',end-start)

输出:

time to download: 2.9488866329193115

1

timetodownload:2.9488866329193115

可以看出,使用多进程后,程序运行的速度更快了。

创建进度条下载

进度条是

clint 模块的一个UI组件。输入以下命令来安装

clint 模块:

pip install clint

1

pipinstallclint

有如下代码:

import requests

from clint.textui import progress

url = 'https://do1.dr-chuck.com/pythonlearn/EN_us/pythonlearn.pdf'

r = requests.get(url, stream=True)

with open('lp.pdf', 'wb') as f:

total_length = int(r.headers.get('content-length'))

for x in progress.bar(r.iter_content(chunk_size=200000), expected_size=(total_length/1024) + 1):

if x:

f.write(x)

1

2

3

4

5

6

7

8

9

10

importrequests

fromclint.textuiimportprogress

url='https://do1.dr-chuck.com/pythonlearn/EN_us/pythonlearn.pdf'

r=requests.get(url,stream=True)

withopen('lp.pdf','wb')asf:

total_length=int(r.headers.get('content-length'))

forxinprogress.bar(r.iter_content(chunk_size=200000),expected_size=(total_length/1024)+1):

ifx:

f.write(x)

在这段代码中,我们首先导入了

requests 模块,然后,我们从

clint.textui 导入了进度组件。唯一的区别是在for循环中。在将内容写入文件时,我们使用了进度条模块的

bar 方法。

总结

本文介绍了Python下载web文件的各种方法,记得点赞收藏哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值