python 下载文件的几种方式分享


Posted in Python onApril 07, 2021

1 、一般同步下载

示例代码:

import requests
import os

def downlaod(url, file_path):
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
  }
  r = requests.get(url=url, headers=headers)
  with open(file_path, "wb") as f:
    f.write(r.content)
    f.flush()

2、 使用流式请求,requests.get方法的stream

默认情况下是stream的值为false,它会立即开始下载文件并存放到内存当中,倘若文件过大就会导致内存不足的情况,程序就会报错。
当把get函数的stream参数设置成True时,它不会立即开始下载,当你使用iter_content或iter_lines遍历内容或访问内容属性时才开始下载,需要注意一点:文件没有下载之前,它也需要保持连接。

iter_content:一块一块的遍历要下载的内容
iter_lines:一行一行的遍历要下载的内容

使用上面两个函数下载大文件可以防止占用过多的内存,因为每次只下载小部分数据。

示例代码:

3 、异步下载文件

由于request的请求是阻塞式的,所以要用aiohttp模块来发起请求。

示例代码:

import aiohttp
import asyncio
import os


async def handler(url, file_path):
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
  }
  async with aiohttp.ClientSession() as session:
    r = await session.get(url=url, headers=headers)
    with open(file_path, "wb") as f:
      f.write(await r.read())
      f.flush()
      os.fsync(f.fileno())


loop = asyncio.get_event_loop()
loop.run_until_complete(handler(url, file_path))

4、 异步拆分下载文件

上面用的是一个协程下载一个文件,下面的方法是将文件分成几部分,每个部分用一个协程下载,最后再写入文件。

下面这个例子用的是流式写入,即把内容写入到磁盘里面。

import aiohttp
import asyncio
import time
import os


async def consumer(queue):
  option = await queue.get()
  start = option["start"]
  end = option["end"]
  url = option["url"]
  filename = option["filename"]
  i = option["i"]

  print(f"第{i}个任务开始运行")
  async with aiohttp.ClientSession() as session:
    headers = {"Range": f"bytes={start}-{end}"}
    r = await session.get(url=url, headers=headers)
    with open(filename, "rb+") as f:
      f.seek(start)
      while True:
        chunk = await r.content.read(end - start)
        if not chunk:
          break
        f.write(chunk)
        f.flush()
        os.fsync(f.fileno())
        print(f"第{i}个任务正在写入中ing")
    queue.task_done()
    print(f"第{i}个任务写入成功")


async def producer(url, headers, filename, queue, coro_num):
  async with aiohttp.ClientSession() as session:
    resp = await session.head(url=url, headers=headers)
    file_size = int(resp.headers["content-length"])
    # 创建一个文件
    with open(filename, "wb") as f:
      pass
    part = file_size // coro_num
    for i in range(coro_num):
      start = part * i
      if i == coro_num - 1:
        end = file_size
      else:
        end = start + part
      info = {
        "start": start,
        "end": end,
        "url": url,
        "filename": filename,
        "i": i,
      }
      queue.put_nowait(info)


async def main():
  # 需要填的有url,filename,coro_num
  url = ""
  filename = ""
  coro_num = 0
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0"
  }
  queue = asyncio.Queue(coro_num)
  await producer(url, headers, filename, queue, coro_num)
  task_list = []
  for i in range(coro_num):
    task = asyncio.create_task(consumer(queue))
    task_list.append(task)
  await queue.join()
  for i in task_list:
    i.cancel()
  await asyncio.gather(*task_list)


startt = time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
end = time.time() - startt
print(f"用了{end}秒")

5、注意

以上的示例都是介绍思路,程序并不健壮,健壮的程序需要加入错误捕获和错误处理。

以上就是python 下载文件的几种方式分享的详细内容,更多关于python 下载文件的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python常用小技巧总结
Jun 01 Python
Python判断Abundant Number的方法
Jun 15 Python
Python中atexit模块的基本使用示例
Jul 08 Python
Python生成随机密码的方法
Jun 16 Python
Python中用字符串调用函数或方法示例代码
Aug 04 Python
解决Python2.7读写文件中的中文乱码问题
Apr 12 Python
Python参数解析模块sys、getopt、argparse使用与对比分析
Apr 02 Python
Python使用enumerate获取迭代元素下标
Feb 03 Python
如何打包Python Web项目实现免安装一键启动的方法
May 21 Python
使用pyplot.matshow()函数添加绘图标题
Jun 16 Python
使用Python将语音转换为文本的方法
Aug 10 Python
python实现商品进销存管理系统
May 30 Python
完美处理python与anaconda环境变量的冲突问题
python 如何用map()函数创建多线程任务
python requests模块的使用示例
Apr 07 #Python
Python 使用dict实现switch的操作
Apr 07 #Python
Python 把两层列表展开平铺成一层(5种实现方式)
Apr 07 #Python
Python获取百度热搜的完整代码
详解Python小数据池和代码块缓存机制
Apr 07 #Python
You might like
YII2框架中添加自定义模块的方法实例分析
2020/03/18 PHP
js电信网通双线自动选择技巧
2008/11/18 Javascript
JQuery与Ajax常用代码实现对比
2009/10/03 Javascript
js函数的引用, 关于内存的开销
2012/09/17 Javascript
js写的方法实现上传图片之后查看大图
2014/03/05 Javascript
iframe子页面与父页面在同域或不同域下的js通信
2014/05/07 Javascript
jQuery表格插件datatables用法详解
2020/11/23 Javascript
jQuery each函数源码分析
2016/05/25 Javascript
JS 根据子网掩码,网关计算出所有IP地址范围示例
2020/04/23 Javascript
js实现下一页页码效果
2017/03/07 Javascript
Angular之toDoList的实现代码示例
2017/12/02 Javascript
Angular2之二级路由详解
2018/08/31 Javascript
vue中v-for通过动态绑定class实现触发效果
2018/12/06 Javascript
nodejs基础之buffer缓冲区用法分析
2018/12/26 NodeJs
简单了解three.js 着色器材质
2020/08/03 Javascript
浅谈Vue使用Elementui修改默认的最快方法
2020/12/05 Vue.js
python通过cookie模拟已登录状态的初步研究
2016/11/09 Python
Python urls.py的三种配置写法实例详解
2017/04/28 Python
python Socket之客户端和服务端握手详解
2017/09/18 Python
Python字符串格式化的方法(两种)
2017/09/19 Python
用python处理图片之打开\显示\保存图像的方法
2018/05/04 Python
python实现黑客字幕雨效果
2018/06/21 Python
python使用matplotlib库生成随机漫步图
2018/08/27 Python
pandas重新生成索引的方法
2018/11/06 Python
python中tab键是什么意思
2020/06/18 Python
python与c语言的语法有哪些不一样的
2020/09/13 Python
前端隐藏出边界内容的实现方法
2016/04/14 HTML / CSS
澳大利亚网上玩具商店:Mr Toys Toyworld
2018/03/25 全球购物
外包公司软件测试工程师
2014/11/01 面试题
介绍一下Java中的static关键字
2012/05/12 面试题
大学生就业自荐信
2013/10/26 职场文书
经济贸易专业自荐信
2014/06/11 职场文书
2015年“7.11”世界人口日宣传活动方案
2015/05/06 职场文书
基于Redis6.2.6版本部署Redis Cluster集群的问题
2022/04/01 Redis
python+opencv实现目标跟踪过程
2022/06/21 Python
使用JS前端技术实现静态图片局部流动效果
2022/08/05 Javascript