使用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 ...
随机推荐
- 代码提示级别设置 inspection
配置文件 profile [ˈproʊfaɪl] n.侧面; 外形,轮廓; 人物简介; vt.描-的轮廓; 给-画侧面图; inspection [ɪnˈspɛkʃən] n.检验; 检查; 视察; ...
- javascript this详解 面向对象
在面向对象编程语言中,对于this关键字我们是非常熟悉的.比如C++.C#和Java等都提供了这个关键字 虽然在开始学习的时候觉得比较难,但只要理解了,用起来是非常方便和意义确定的.JavaS ...
- Gridview 单选效果实现,且用且珍惜
Gridview 单选效果,在androidapp中实现非常频繁,我这里提供我的一种思路,这是我的思维导图: 怎么样将这样的思维导图翻译成java代码了,请看下面的代码了: // 电子产品的图片列表信 ...
- 在浏览器中直接调用webservice的正确写法
此文章针对webwork+spring+hibernate的工程,对于其他框架应该一样适用,首先在wsdd文件中找到所需webservice的名称,例如以下写法: <service name=& ...
- R读 txt 文件
house<-read.table("house_data.txt", header = TRUE, sep='|',fileEncoding ='UTF-8') id|ho ...
- 【图片识别】Java中使用tess4J进行图片文字识别(支持中文)(转)
http://blog.csdn.net/wsk1103/article/details/54173282 java中识别文字比较简单,使用的软件是tesseractocr(使用的版本是3.02,3以 ...
- Mac OS X /home 目录权限修改
Mac OS X /home 目录权限修改 http://ju.outofmemory.cn/entry/283070 sudo vi /etc/auto_master # 注释掉 /home那一行 ...
- google test框架与eclipse插件
1. https://github.com/google/googletest (google的测试框架) 2. eclipse测试框架插件 https://github.com/xgsa/cd ...
- unity3d shader 学习
[浅墨Unity3D Shader编程] 着色器参考 [Unity Shaders]
- python绘制很美丽的图表
或许你会觉得python不适合做图形界面的开发,的确如此.可是python却有一个非常美丽的图标模块:pycha,废话少说,先上图,各位看一下. 是不是效果还不错呢,当然这仅仅是一小部分图表,还有其它 ...