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解决方案:WindowsError: [Error 2]
Aug 28 Python
Python实现读取json文件到excel表
Nov 18 Python
关于反爬虫的一些简单总结
Dec 13 Python
Python多线程threading和multiprocessing模块实例解析
Jan 29 Python
python实现自动网页截图并裁剪图片
Jul 30 Python
django项目简单调取百度翻译接口的方法
Aug 06 Python
详解Django CAS 解决方案
Oct 30 Python
关于numpy数组轴的使用详解
Dec 05 Python
使用python去除图片白色像素的实例
Dec 12 Python
Python基础之变量基本用法与进阶详解
Jan 03 Python
python 发送get请求接口详解
Nov 17 Python
python3.9之你应该知道的新特性详解
Apr 29 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
其他功能
2006/10/09 PHP
PHP内核探索:变量概述
2014/01/30 PHP
PHP浮点数精度问题汇总
2015/05/13 PHP
yii2中的rules 自定义验证规则详解
2016/04/19 PHP
Laravel 中使用 Vue.js 实现基于 Ajax 的表单提交错误验证操作
2017/06/30 PHP
php+Ajax处理xml与json格式数据的方法示例
2019/03/04 PHP
greybox——不开新窗口看新的网页
2007/02/20 Javascript
解决表单中第一个非隐藏的元素获得焦点的一个方案
2009/10/26 Javascript
Json对象替换字符串占位符实现代码
2010/11/17 Javascript
js TextArea的选中区域处理
2010/12/28 Javascript
js中使用DOM复制(克隆)指定节点名数据到新的XML文件中的代码
2011/07/27 Javascript
当前流行的JavaScript代码风格指南
2014/09/10 Javascript
JS实现设置ff与ie元素绝对位置的方法
2016/03/08 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
函数四种调用模式以及其中的this指向
2017/01/16 Javascript
JavaScript使用原型和原型链实现对象继承的方法详解
2017/04/05 Javascript
使用Require.js封装原生js轮播图的实现代码
2017/06/15 Javascript
Node.js学习之查询字符串解析querystring详解
2017/09/28 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
js中Generator函数的深入讲解
2019/04/07 Javascript
在node环境下parse Smarty模板的使用示例代码
2019/11/15 Javascript
vue 避免变量赋值后双向绑定的操作
2020/11/07 Javascript
vc6编写python扩展的方法分享
2014/01/17 Python
使用apidocJs快速生成在线文档的实例讲解
2018/02/07 Python
python模拟键盘输入 切换键盘布局过程解析
2019/08/15 Python
HTML5实现文件断点续传的方法
2017/01/04 HTML / CSS
JSF的标签库有哪些
2012/04/27 面试题
《我不是最弱小的》教学反思
2014/02/23 职场文书
求职个人评价范文
2014/04/09 职场文书
大学毕业生个人自荐书
2014/07/02 职场文书
车间主任岗位职责
2015/02/03 职场文书
军事博物馆观后感
2015/06/05 职场文书
党员公开承诺书2016
2016/03/24 职场文书
浅谈redis五大数据结构和使用场景
2021/04/12 Redis
Java 通过手写分布式雪花SnowFlake生成ID方法详解
2022/04/07 Java/Android