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 相关文章推荐
wxPython事件驱动实例详解
Sep 28 Python
Python pickle模块用法实例分析
May 27 Python
举例讲解Python设计模式编程中对抽象工厂模式的运用
Mar 02 Python
Django的信号机制详解
May 05 Python
Python实现基于PIL和tesseract的验证码识别功能示例
Jul 11 Python
python Pandas如何对数据集随机抽样
Jul 29 Python
浅析使用Python搭建http服务器
Oct 27 Python
Python基础之字符串常见操作经典实例详解
Feb 26 Python
Python3获取cookie常用三种方案
Oct 05 Python
Python数据分析库pandas高级接口dt的使用详解
Dec 11 Python
PyQt5 显示超清高分辨率图片的方法
Apr 11 Python
七个非常实用的Python工具包总结
Jun 15 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+ACCESS 文章管理程序代码
2010/06/21 PHP
利用浏览器的Javascript控制台调试PHP程序
2014/01/08 PHP
Yii2数据库操作常用方法小结
2017/05/04 PHP
关于document.cookie的使用javascript
2008/04/11 Javascript
JavaScript 动态将数字金额转化为中文大写金额
2009/05/14 Javascript
javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关系
2010/02/04 Javascript
JQuery入门——事件切换之hover()方法应用介绍
2013/02/05 Javascript
关于jQuery参考实例 1.0 jQuery的哲学
2013/04/07 Javascript
JQuery实现动态适时改变字体颜色的方法
2015/03/10 Javascript
js实现文本框选中的方法
2015/05/26 Javascript
javascript同步服务器时间和同步倒计时小技巧
2015/09/24 Javascript
Nodejs中session的简单使用及通过session实现身份验证的方法
2016/02/04 NodeJs
基于vue+ bootstrap实现图片上传图片展示功能
2017/05/17 Javascript
jQuery中复合选择器简单用法示例
2018/03/31 jQuery
vue组件实现可搜索下拉框扩展
2020/10/23 Javascript
jQuery实现表单动态添加数据并提交的方法
2018/07/19 jQuery
关于Vue中axios的封装实例详解
2019/10/20 Javascript
BootstrapValidator验证用户名已存在(ajax)
2019/11/08 Javascript
详解Vue的组件中data选项为什么必须是函数
2020/08/17 Javascript
jQuery实现简单弹幕制作
2020/12/10 jQuery
[40:05]DOTA2上海特级锦标赛A组小组赛#1 EHOME VS MVP.Phx第一局
2016/02/25 DOTA
python生成IP段的方法
2015/07/07 Python
利用Python批量生成任意尺寸的图片
2016/08/29 Python
Python中多个数组行合并及列合并的方法总结
2018/04/12 Python
启动Atom并运行python文件的步骤
2018/11/09 Python
Django使用消息提示简单的弹出个对话框实例
2019/11/15 Python
基于python的列表list和集合set操作
2019/11/24 Python
python 轮询执行某函数的2种方式
2020/05/03 Python
如何用python免费看美剧
2020/08/11 Python
For Art’s Sake官网:手工制作的奢华眼镜
2018/12/15 全球购物
服装机修工岗位职责
2013/12/26 职场文书
班组长安全职责
2014/01/05 职场文书
导游词之新疆-喀纳斯
2019/10/10 职场文书
详解如何修改nginx的默认端口
2021/03/31 Servers
Golang 语言控制并发 Goroutine的方法
2021/06/30 Golang
MySQL生成千万测试数据以及遇到的问题
2022/08/05 MySQL