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解决字典中的值是列表问题的方法
Mar 04 Python
老生常谈Python序列化和反序列化
Jun 28 Python
python导出hive数据表的schema实例代码
Jan 22 Python
python中ASCII码字符与int之间的转换方法
Jul 09 Python
用Q-learning算法实现自动走迷宫机器人的方法示例
Jun 03 Python
python删除列表元素的三种方法(remove,pop,del)
Jul 22 Python
Flask框架模板继承实现方法分析
Jul 31 Python
解析python实现Lasso回归
Sep 11 Python
pandas数据处理进阶详解
Oct 11 Python
Python unittest单元测试openpyxl实现过程解析
May 27 Python
python中实现栈的三种方法
Dec 19 Python
Python数据类型最全知识总结
May 31 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中与数组相关的函数
2007/03/22 PHP
一个简单的网页密码登陆php代码
2012/07/17 PHP
PHP中使用break跳出多重循环代码实例
2015/01/21 PHP
PHP中生成UUID自定义函数分享
2015/06/10 PHP
简单实用的PHP文本缓存类实例
2019/03/22 PHP
如何取得中文输入的真实长度?
2006/06/24 Javascript
保证JavaScript和Asp、Php等后端程序间传值编码统一
2009/04/17 Javascript
jquery中filter方法用法实例分析
2015/02/06 Javascript
javascript显式类型转换实例分析
2015/04/25 Javascript
Javascript基础教程之比较null和undefined值
2016/05/16 Javascript
JS添加删除DIV的简单实例
2016/07/08 Javascript
浅述节点的创建及常见功能的实现
2016/12/15 Javascript
JS中传递参数的几种不同方法比较
2017/01/20 Javascript
限时抢购-倒计时的完整实例(分享)
2017/09/17 Javascript
关于 angularJS的一些用法
2017/11/29 Javascript
详解ES6语法之可迭代协议和迭代器协议
2018/01/13 Javascript
使用淘宝镜像cnpm安装Vue.js的图文教程
2018/05/17 Javascript
jQuery实现参数自定义的文字跑马灯效果
2018/08/15 jQuery
vue-cli 3.0 版本与3.0以下版本在搭建项目时的区别详解
2018/12/11 Javascript
layui使用label标签的方法
2019/09/14 Javascript
vue路由守卫,限制前端页面访问权限的例子
2019/11/11 Javascript
django批量导入xml数据
2016/10/16 Python
深入理解python对json的操作总结
2017/01/05 Python
Python与Java间Socket通信实例代码
2017/03/06 Python
python实现彩票系统
2020/06/28 Python
用python写爬虫简单吗
2020/07/28 Python
Python基于staticmethod装饰器标示静态方法
2020/10/17 Python
Python图像识别+KNN求解数独的实现
2020/11/13 Python
HTML5中原生的右键菜单创建方法
2016/06/28 HTML / CSS
美国创意礼品网站:UncommonGoods
2017/02/03 全球购物
为什么说Ruby是一种真正的面向对象程序设计语言
2012/10/30 面试题
《乌塔》教学反思
2014/02/17 职场文书
培训科主任岗位职责
2014/08/08 职场文书
母亲节主题班会
2015/08/14 职场文书
来探秘“德国中小企业”的成功之道
2019/07/26 职场文书
SpringMVC 整合SSM框架详解
2021/08/30 Java/Android