窗外下着小雨,作为单身程序员的我逛着逛着发现一篇好东西,来自知乎 你都用 Python 来做什么?的第一个高亮答案。
到上面去看了看,地址都是明文的,得,赶紧开始吧。
下载流式文件,requests库中请求的stream设为True就可以啦,文档在此。
先找一个视频地址试验一下:
# -*- coding: utf-8 -*- import requests def download_file(url, path): with requests.get(url, stream=True) as r: chunk_size = 1024 content_size = int(r.headers['content-length']) print '下载开始' with open(path, "wb") as f: for chunk in r.iter_content(chunk_size=chunk_size): f.write(chunk) if __name__ == '__main__': url = '就在原帖...' path = '想存哪都行' download_file(url, path)
遭遇当头一棒:
AttributeError: __exit__
这文档也会骗人的么!
看样子是没有实现上下文需要的__exit__方法。既然只是为了保证要让r最后close以释放连接池,那就使用contextlib的closing特性好了:
# -*- coding: utf-8 -*- import requests from contextlib import closing def download_file(url, path): with closing(requests.get(url, stream=True)) as r: chunk_size = 1024 content_size = int(r.headers['content-length']) print '下载开始' with open(path, "wb") as f: for chunk in r.iter_content(chunk_size=chunk_size): f.write(chunk)
程序正常运行了,不过我盯着这文件,怎么大小不见变啊,到底是完成了多少了呢?还是要让下好的内容及时存进硬盘,还能省点内存是不是:
# -*- coding: utf-8 -*- import requests from contextlib import closing import os def download_file(url, path): with closing(requests.get(url, stream=True)) as r: chunk_size = 1024 content_size = int(r.headers['content-length']) print '下载开始' with open(path, "wb") as f: for chunk in r.iter_content(chunk_size=chunk_size): f.write(chunk) f.flush() os.fsync(f.fileno())
文件以肉眼可见的速度在增大,真心疼我的硬盘,还是最后一次写入硬盘吧,程序中记个数就好了:
def download_file(url, path): with closing(requests.get(url, stream=True)) as r: chunk_size = 1024 content_size = int(r.headers['content-length']) print '下载开始' with open(path, "wb") as f: n = 1 for chunk in r.iter_content(chunk_size=chunk_size): loaded = n*1024.0/content_size f.write(chunk) print '已下载{0:%}'.format(loaded) n += 1
结果就很直观了:
已下载2.579129% 已下载2.581255% 已下载2.583382% 已下载2.585508%
心怀远大理想的我怎么会只满足于这一个呢,写个类一起使用吧:
# -*- coding: utf-8 -*- import requests from contextlib import closing import time def download_file(url, path): with closing(requests.get(url, stream=True)) as r: chunk_size = 1024*10 content_size = int(r.headers['content-length']) print '下载开始' with open(path, "wb") as f: p = ProgressData(size = content_size, unit='Kb', block=chunk_size) for chunk in r.iter_content(chunk_size=chunk_size): f.write(chunk) p.output() class ProgressData(object): def __init__(self, block,size, unit, file_name='', ): self.file_name = file_name self.block = block/1000.0 self.size = size/1000.0 self.unit = unit self.count = 0 self.start = time.time() def output(self): self.end = time.time() self.count += 1 speed = self.block/(self.end-self.start) if (self.end-self.start)>0 else 0 self.start = time.time() loaded = self.count*self.block progress = round(loaded/self.size, 4) if loaded >= self.size: print u'%s下载完成\r\n'%self.file_name else: print u'{0}下载进度{1:.2f}{2}/{3:.2f}{4} 下载速度{5:.2%} {6:.2f}{7}/s'.\ format(self.file_name, loaded, self.unit,\ self.size, self.unit, progress, speed, self.unit) print '%50s'%('/'*int((1-progress)*50))
运行:
下载开始 下载进度10.24Kb/120174.05Kb 0.01% 下载速度4.75Kb/s ///////////////////////////////////////////////// 下载进度20.48Kb/120174.05Kb 0.02% 下载速度32.93Kb/s /////////////////////////////////////////////////
看上去舒服多了。
下面要做的就是多线程同时下载了,主线程生产url放入队列,下载线程获取url:
# -*- coding: utf-8 -*- import requests from contextlib import closing import time import Queue import hashlib import threading import os def download_file(url, path): with closing(requests.get(url, stream=True)) as r: chunk_size = 1024*10 content_size = int(r.headers['content-length']) if os.path.exists(path) and os.path.getsize(path)>=content_size: print '已下载' return print '下载开始' with open(path, "wb") as f: p = ProgressData(size = content_size, unit='Kb', block=chunk_size, file_name=path) for chunk in r.iter_content(chunk_size=chunk_size): f.write(chunk) p.output() class ProgressData(object): def __init__(self, block,size, unit, file_name='', ): self.file_name = file_name self.block = block/1000.0 self.size = size/1000.0 self.unit = unit self.count = 0 self.start = time.time() def output(self): self.end = time.time() self.count += 1 speed = self.block/(self.end-self.start) if (self.end-self.start)>0 else 0 self.start = time.time() loaded = self.count*self.block progress = round(loaded/self.size, 4) if loaded >= self.size: print u'%s下载完成\r\n'%self.file_name else: print u'{0}下载进度{1:.2f}{2}/{3:.2f}{4} {5:.2%} 下载速度{6:.2f}{7}/s'.\ format(self.file_name, loaded, self.unit,\ self.size, self.unit, progress, speed, self.unit) print '%50s'%('/'*int((1-progress)*50)) queue = Queue.Queue() def run(): while True: url = queue.get(timeout=100) if url is None: print u'全下完啦' break h = hashlib.md5() h.update(url) name = h.hexdigest() path = 'e:/download/' + name + '.mp4' download_file(url, path) def get_url(): queue.put(None) if __name__ == '__main__': get_url() for i in xrange(4): t = threading.Thread(target=run) t.daemon = True t.start()
加了重复下载的判断,至于怎么源源不断的生产url,诸位摸索吧,保重身体!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍基于python爬取梨视频实现过程解析,包括了基于python爬取梨视频实现过程解析的使用技巧和注意事项,需要的朋友参考一下 目标网址:梨视频 然后我们找到科技这一页:https://www.pearvideo.com/category_8。其实你要哪一页都行,你喜欢就行。嘿嘿… 这是动态网站,所以咱们直奔network 然后去到XHR: 找规律,这个应该不难,我就直接贴网址上来咯,
本文向大家介绍Python爬虫 bilibili视频弹幕提取过程详解,包括了Python爬虫 bilibili视频弹幕提取过程详解的使用技巧和注意事项,需要的朋友参考一下 两个重要点 1.获取弹幕的url是以 .xml 结尾 2.弹幕url的所需参数在视频url响应的 javascript 中 先看代码 先找到弹幕的url,以.xml结尾,所以先找到这串数字所在的位置,并获取这串数字发起第二次请求
本文向大家介绍python爬虫线程池案例详解(梨视频短视频爬取),包括了python爬虫线程池案例详解(梨视频短视频爬取)的使用技巧和注意事项,需要的朋友参考一下 python爬虫-梨视频短视频爬取(线程池) 示例代码 知识点扩展: Python爬虫下载视频(梨视频) 梨视频示例:Ctrl+Alt+L格式化代码 到此这篇关于python爬虫线程池案例详解(梨视频短视频爬取)的文章就介绍到这了,更多
本文向大家介绍Python爬虫爬取博客实现可视化过程解析,包括了Python爬虫爬取博客实现可视化过程解析的使用技巧和注意事项,需要的朋友参考一下 源码: 爬虫不是重点,只是拿来爬阅读数量,pyecharts是重点 这次爬的是我自己的博客,一共10页,每页10片文章,正好写了100篇博客 pyecharts安装: pip install wheelpip install pyecharts==0.
本文向大家介绍Python Scrapy多页数据爬取实现过程解析,包括了Python Scrapy多页数据爬取实现过程解析的使用技巧和注意事项,需要的朋友参考一下 1.先指定通用模板 url = 'https://www.qiushibaike.com/text/page/%d/'#通用的url模板 pageNum = 1 2.对parse方法递归处理 parse第一次调用表示的是用来解析第一页对
本文向大家介绍python爬取youtube视频的示例代码,包括了python爬取youtube视频的示例代码的使用技巧和注意事项,需要的朋友参考一下 这几天正在追剧,原名《大秦帝国之天下》的《大秦赋》,看着看着又想把前几部刷一遍了,但第一部《裂变》自己没有高清资源,搜了一波发现youtube上有个48集版的高清资源,有删减就有删减吧,就想着写个脚本批量下载一下,记录一下过程,主要是youtu