文件下载
- 1. 小文件下载
- 2. 大文件下载
- 3. 异步批量文件下载
1. 小文件下载
基于requests模块的get()函数下载。下载原理如下:先将文件内容保存至变量(即设备内存)中,然后再保存至指定文件中。这种下载有一个最大的限制是内存大小。
import requests
def request_zip(url):
rc = requests.get(url)
# 请求链接后保存到链接变量 rc 中
with open("Download_test.jpg", 'wb') as fout:
# rc.content 写入文件
fout.write(rc.content)
if __name__ == '__main__':
url = "https://pic3.zhimg.com/80/v2-9add4b1033b586a16afd567647326441_720w.jpg"
request_zip(url)
2. 大文件下载
不同于小文件下载,如果将待下载数据保存至内存中,然后再提取保存至本地文件,会因内存的大小受到限制,甚至中断下载。
对于大文件的下载:采用分块方法,将文件按照指定大小,逐块下载数据并写入的指定文件,避免占用过大内存。
import requests
def request_zip(url):
rc = requests.get(url)
# 请求链接后保存到链接变量 rc 中
with open("Download_test.jpg", 'wb') as fout:
# rc.content 写入文件
fout.write(rc.content)
def download_bigData(url):
# stream = True 设置为流读取
rg = requests.get(url, stream=True)
with open("Download_bigTest.jpg", "wb") as fout:
for chunk in rg.iter_content(chunk_size=256):
# 以256个字节为一块,读取文件
if chunk:
# 如果chunk不为空
fout.write(chunk)
if __name__ == '__main__':
url = "https://pic3.zhimg.com/80/v2-9add4b1033b586a16afd567647326441_720w.jpg"
# request_zip(url)
download_bigData(url)
3. 异步批量文件下载
所谓批量下载,非一个一个文件的下载,如果一个一个下载会出现两种负面情况:
- 如果某个请求堵塞,整个队列都会被堵塞
- 如果是小文件,单线程下载太慢
解决方案是使用 异步策略。接下来,我们来讲解如何手动实现异步策略。
- 安装模块
- asyncio
- aiohttp. asyncio (Python3的原装库),但是aiohttp则需要手动安装:
pip install aiohttp
注意 :asyncio是单进程并发库,不是多线程,也不是多进程,单纯是在一个进程里面异步(切来切去运行),切换的地方用await标记,能够切换的函数用async标记。比如异步批量下载两个图片的代码如下:
import requests
import aiohttp
import asyncio
import time
def request_zip(url):
rc = requests.get(url)
# 请求链接后保存到链接变量 rc 中
with open("Download_test.jpg", 'wb') as fout:
# rc.content 写入文件
fout.write(rc.content)
def download_bigData(url):
# stream = True 设置为流读取
rg = requests.get(url, stream=True)
with open("Download_bigTest.jpg", "wb") as fout:
for chunk in rg.iter_content(chunk_size=256):
# 以256个字节为一块,读取文件
if chunk:
# 如果chunk不为空
fout.write(chunk)
async def job(session, url):
# 声明为异步函数
name = url.split('/')[-1]
# 获得名字
img = await session.get(url)
# 触发到await就切换,等待get到数据
imgcode = await img.read()
# 读取内容
with open(str(name), "wb") as fout:
# 写入文件
fout.write(imgcode)
return str(url)
async def main(loop, url):
async with aiohttp.ClientSession() as session:
# 建立会话 session
tasks = [loop.create_task(job(session, url[_])) for _ in range(2)]
# 建立所有任务
finshed, unfinshed = await asyncio.wait(tasks)
# 触发await,等待任务完成
all_results = [r.result() for r in finshed]
# 获取所有结果
print("ALL RESULTS:" + str(all_results))
if __name__ == '__main__':
# url = "https://pic3.zhimg.com/80/v2-9add4b1033b586a16afd567647326441_720w.jpg"
# request_zip(url)
# download_bigData(url)
urllst = ["https://pic3.zhimg.com/80/v2-999dedf65c41973c21e05e435c2ee536_720w.jpg", \
"https://picb.zhimg.com/80/v2-3dc4b27d86e5b870074898cf6532efee_720w.jpg"]
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop, urllst))
注意:img = await session.get(url)
这时候,在你请求第一个图片获得数据的时候,它会切换请求第二个图片或其他图片,等第一个图片获得所有数据后再切换回来。从而实现多线程批量下载的功能,速度超快,下载超清大图用这个方法可以一秒一张。