使用requests库实现多线程下载
多线程下载主要用到http请求中的header
- Content-Length:资源长度,用于确认资源的总长度,从而便于规划每个线程的任务量
- Range:bytes=beg1-end1;beg2-end2,用来控制下载的资源的某一部分,需要注意,这里的beg、end是前闭后闭区间。
当下载的片段较小时,很容易出错,需要重试,可以使用retry模块通过注解方式实现重试,这个模块非常好用。
Python的多线程没有体现出优势来。链条的强度取决于最薄弱的一环,木桶的容量取决于最短的木板,系统的的并发量取决于并发量最小的模块。多线程体现不出优势,可能是因为网速。如果单线程就能够将网速充分利用起来,那么多线程就没有用了。
import os
import threading
import time
import requests
import retry
url = 'http://mp4.vjshi.com/2017-12-18/422ded2944a95d6ca09752e04f687dd6.mp4'
def one_thread():
# 37.86秒
begTime = time.time()
resp = requests.get(url)
with open("haha.mp4", "wb") as f:
f.write(resp.content)
endTime = time.time()
print(endTime - begTime)
def multi_thread():
PER_THREAD_MIN = 2000 # 每个线程至少下载量
MAX_THREAD_COUNT = 50 # 最多线程数
TEMP_FOLDER = "dow" # 临时文件夹
TARGET_FILE_NAME = "mul.mp4" # 存储目标
if not os.path.exists(TEMP_FOLDER):
os.mkdir(TEMP_FOLDER)
begTime = time.time()
resp = requests.get(url, stream=True)
sz = int(resp.headers['Content-Length'])
block_sz = max(sz // MAX_THREAD_COUNT, PER_THREAD_MIN)
task = []
cnt = 0
for i in range(0, sz, block_sz):
now_sz = sz - i if sz - i - block_sz < PER_THREAD_MIN else block_sz
it = {
'beg': i,
'end': i + now_sz,
'path': os.path.join(TEMP_FOLDER, str(cnt)),
'last': i + now_sz == sz
}
task.append(it)
cnt += 1
if it['last']:
break
lock = threading.Lock()
def merge():
with open(TARGET_FILE_NAME, "wb") as f:
for j, i in enumerate(task):
with open(i['path'], 'rb') as ff:
f.write(ff.read(i['end'] - i['beg']))
endTime = time.time()
print(endTime - begTime)
@retry.retry(tries=100)
def go(it):
nonlocal cnt
print(it)
resp = requests.get(url, headers={
'Range': "bytes=%d-%d" % (it['beg'], it['end'] - 1)
})
if resp.status_code not in [200, 206]:
print(it, resp.status_code, '爬虫失败')
raise Exception("爬虫失败")
if len(resp.content) != it['end'] - it['beg']:
print("长度不对")
raise Exception("长度不对")
with open(it['path'], 'wb') as f:
f.write(resp.content)
print(it, it['end'] - it['beg'], len(resp.content), 'over', resp.status_code)
lock.acquire(timeout=0)
cnt -= 1
if cnt == 0:
merge()
lock.release()
def start_threading():
for i in task:
threading.Thread(target=go, args=(i,)).start()
start_threading()
# one_thread()
multi_thread()
使用requests库实现多线程下载的更多相关文章
- HTTP多线程下载+断点续传(libcurl库)
目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_perform 函数说明(error 状态码) 五.lib ...
- requests库下载图片的方法
方法: 传入图片url,requests.get()方法请求一下,将源码以二进制的形式写在本地即可. 以前一直以为requests库中有特定的方法获取图片,类似urllib.request.urlre ...
- python下载安装requests库
一.python下载安装requests库 1.到git下载源码zip源码https://github.com/requests/requests 2.解压到python目录下: 3.“win+R”进 ...
- requests库入门12-文件上传和下载
因为找不到可以演示上传接口,所以只能纯代码了 文件上传 上传文件是在请求中使用files参数,files需要指向一个dict,然后dict里面的键是接口中对应文件名的字段,而值就是打开这个文件读取到内 ...
- 从0开始学爬虫11之使用requests库下载图片
从0开始学爬虫11之使用requests库下载图片 # coding=utf-8 import requests def download_imgage(): ''' demo: 下载图片 ''' h ...
- 下载requests库
下载requests库 第一步:找到python的安装位置,可以从下面的图中找到 第二步:复制scripts文件夹的位置 第三步:win+r打开cmd cd 到scripts文件夹的位置 第四步:运行 ...
- Python爬虫之多线程下载豆瓣Top250电影图片
爬虫项目介绍 本次爬虫项目将爬取豆瓣Top250电影的图片,其网址为:https://movie.douban.com/top250, 具体页面如下图所示: 本次爬虫项目将分别不使用多线程和使 ...
- 【转载-译文】requests库连接池说明
转译自:https://laike9m.com/blog/requests-secret-pool_connections-and-pool_maxsize,89/ Requests' secret: ...
- python -使用Requests库完成Post表单操作
""" 使用Requests库完成Post表单操作 """ #_*_codingn:utf8 _*_ import requests fro ...
随机推荐
- 算法 数组中出现次数最多的数字 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 理解TensorFlow的Queue
https://www.jianshu.com/p/d063804fb272 这篇文章来说说TensorFlow里与Queue有关的概念和用法. 其实概念只有三个: Queue是TF队列和缓存机制的实 ...
- 理解MySQL数据库覆盖索引 (转)
http://www.cnblogs.com/zl0372/articles/mysql_32.html 话说有这么一个表: CREATE TABLE `user_group` ( `id` int( ...
- wifidog 源码初分析(4)-转
在上一篇<wifidog 源码处分析(3)>的流程结束后,接入设备的浏览器重定向至 路由器 上 wifidog 的 http 服务(端口 2060) /wifidog/auth 上(且携带 ...
- 解决webstom failed to change read-only files
我百思不得其解的是,为何我的文件不让我更改,变成了只读模式,后来我仔细回忆了一下,原来是因为我使用了root权限,来安装thinkjs之后,webstom没有root权限,所以我使用root,在终端敲 ...
- 判断一个整数是否是2的n次方
参考:http://bbs.csdn.net/topics/370058619 如题,如何判断一个整数是否是2的N次方,我能想到的方法有两个 1.一直除2,看最后是否等于1.(最笨的方法) 2.转换成 ...
- Python代码规范(PEP8)问题及解决
转载:https://blog.csdn.net/Jason_Lewis/article/details/75386598 最近刚刚接触Python,为了养成好习惯,尽量保证自己写的代码符合PEP8代 ...
- Jackcard类似度和余弦类似度(向量空间模型)的java实现
版权声明:本文为博主原创文章,地址:http://blog.csdn.net/napoay,转载请留言. 总结Jackcard类似度和余弦类似度. 一.集合的Jackcard类似度 1.1Jackca ...
- ArcEngine应用程序中无法实现TOC图层多选
在ArcMap的内容列表中,Ctrl和Shift多选.反选等操作图层非常方便. 然而遗憾的是:经测试,查证在ArcEngine应用程序中无法使用此接口,只能通过在Desktop中来使用IContent ...
- SDE注册版本失败,仅支持一个空间列
如果直接编辑SDE要素类与要素可以不需要版本,使用默认版本,如果要让用户通过界面编辑,即使用开启编辑.保存编辑和停止编辑,就需要注册为版本,而在注册版本弹出如下错误: 正如错误所说,一个要素类或shp ...