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 del()函数用法
Mar 24 Python
Python入门及进阶笔记 Python 内置函数小结
Aug 09 Python
python使用calendar输出指定年份全年日历的方法
Apr 04 Python
Python中的getopt函数使用详解
Jul 28 Python
Python使用 Beanstalkd 做异步任务处理的方法
Apr 24 Python
Python查看微信撤回消息代码
Jun 07 Python
Python爬虫动态ip代理防止被封的方法
Jul 07 Python
手把手教你Python yLab的绘制折线图的画法
Oct 23 Python
python使用多线程+socket实现端口扫描
May 28 Python
Python数据可视化实现多种图例代码详解
Jul 14 Python
python爬虫分布式获取数据的实例方法
Nov 26 Python
python 图像增强算法实现详解
Jan 24 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
PHP多文件上传类实例
2015/03/07 PHP
PHP输出两个数字中间有多少个回文数的方法
2015/03/23 PHP
php调整服务器时间的方法
2015/04/03 PHP
php结合正则批量抓取网页中邮箱地址
2015/05/19 PHP
PHP使用DOM和simplexml读取xml文档的方法示例
2017/02/08 PHP
MooTools 1.2中的Drag.Move来实现拖放
2009/09/15 Javascript
js实现右下角可关闭最小化div(可用于展示推荐内容)
2013/06/24 Javascript
jquery导航制件jquery鼠标经过变色效果示例
2013/12/05 Javascript
Angularjs编写KindEditor,UEidtor,jQuery指令
2015/01/28 Javascript
jquery中EasyUI实现同步树
2015/03/01 Javascript
javascript实现类似java中getClass()得到对象类名的方法
2015/07/27 Javascript
nodejs初步体验篇
2015/11/23 NodeJs
webpack处理 css\less\sass 样式的方法
2017/08/21 Javascript
Angular搜索 过滤 批量删除 添加 表单验证功能集锦(实例代码)
2017/10/25 Javascript
在 vue-cli v3.0 中使用 SCSS/SASS的方法
2018/06/14 Javascript
基于bootstrap页面渲染的问题解决方法
2018/08/09 Javascript
微信小程序实现日历效果
2018/12/28 Javascript
Element-UI中Upload上传文件前端缓存处理示例
2019/02/21 Javascript
layui 上传插件 带预览 非自动上传功能的实例(非常实用)
2019/09/23 Javascript
vue实现折线图 可按时间查询
2020/08/21 Javascript
微信小程序换肤功能实现代码(思路详解)
2020/08/25 Javascript
基于JavaScript实现简单扫雷游戏
2021/01/02 Javascript
[01:25]2014DOTA2国际邀请赛 zhou分析LGD比赛情况
2014/07/14 DOTA
Python温度转换实例分析
2018/01/17 Python
python2.x实现人民币转大写人民币
2018/06/20 Python
解决python报错MemoryError的问题
2018/06/26 Python
python笔记_将循环内容在一行输出的方法
2019/08/08 Python
python使用ctypes调用扩展模块的实例方法
2020/01/28 Python
Python猴子补丁Monkey Patch用法实例解析
2020/03/23 Python
TensorFlow2.0使用keras训练模型的实现
2021/02/20 Python
CSS3 2D模拟实现摩天轮旋转效果
2016/11/16 HTML / CSS
Skyscanner新西兰:全球领先的旅游搜索网站
2019/08/26 全球购物
请解释流与文件有什么不同
2016/07/29 面试题
网络程序员自荐信
2014/01/25 职场文书
股权转让协议书
2014/04/12 职场文书
培训后的感想
2015/08/07 职场文书