博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python3——根据m3u8下载视频(上)之urllib.request
阅读量:5340 次
发布时间:2019-06-15

本文共 3779 字,大约阅读时间需要 12 分钟。

    干活干活,区区懒癌已经阻挡不了澎湃的洪荒之力了......   

运行环境:Windows基于python3.6

     -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------

        抓取视频时遇到M3U8的确挺烦人的,去年年底实习,由于项目需求所以和一个同事主攻蟒蛇爬虫,抓取含有清晰人脸的图片和视频,在爬取一些视频网站和直播网站时就被“它”糊了一脸,作为一只,呃,不对,是两只刚入爬虫坑的菜鸟,在视频加载播放时找不到啥关于的.mp4,.MKV的链接,反而出现不少.ts的链接,然后爬取找度娘,重点如下:

        M3U8是苹果公司推出一种视频播放标准,是一种文件检索格式,将视频切割成一小段一小段的TS格式的视频文件,然后存在服务器中(现在为了减少I / O访问次数,一般存在服务器的内存中),通过M3U8解析出来路径,然后去请求,是现在比较流行的一种加载方式,诸如腾讯视频之类大多都是切割成TS流进行加载。

        但当时还是晕,理论和实际处理是两回事,那时候关于如何爬取M3U8的博客不是很多而且很少说到重点(给俺下载代码,理论改天再补)样么是其它语言写的更懵,近来倒是越来越多了(可惜当时没赶上),最后找到篇关于下载的却发现是python2的代码,因为那时候刚开始使用蟒之前学的是Java中,所以调了好一会还是运行失败,但是也收获了不少,之后和同事研究了两天试验了几个方案最终确定采用边下边合的方式进行处理,上个月底从公司离职了,由于公司管理较为严格禁止向外网(公司局域网以外)发送消息或拷贝文件,(嗯,拍照也不行,就似〜这么严)所以这几天晚上下班回来抽空写写改改又另起了炉灶,代码如下,随意写的所以异常处理和模拟浏览器啥的就没加了(懒)!

注:仅限窗口下使用,如果要在Linux的上使用需要修改合并命令,嗯,或者等几天我再来篇兼容的

​# !/user/bin/env python# -*- coding: utf-8 -*-# au: caopeiya# 20180808import os, shutilimport urllib.request, urllib.error, requests# 打开并读取网页内容def getUrlData(url):    try:        urlData = urllib.request.urlopen(url, timeout=20)  # .read().decode('utf-8', 'ignore')        return urlData    except Exception as err:        print(f'err getUrlData({url})\n', err)        return -1# 下载文件-urllib.requestdef getDown_urllib(url, file_path):    try:        urllib.request.urlretrieve(url, filename=file_path)        return True    except urllib.error.URLError as e:        # hasttr(e, 'code'),判断e 是否有.code属性,因为不确定是不是HTTPError错误,URLError包含HTTPError,但是HTTPError以外的错误是不返回错误码(状态码)的        if hasattr(e, 'code'):            print(e.code)  # 打印服务器返回的错误码(状态码),如403,404,501之类的        elif hasattr(e, 'reason'):            print(e.reason)  # 打印错误原因def getVideo_urllib(url_m3u8, path, videoName):    print('begin run ~~\n')    # urlData = getUrlData(url_m3u8).readlines()    urlData = getUrlData(url_m3u8)    num = 0    tempName_video = os.path.join(path, f'{videoName}.ts')  # f'{}' 相当于'{}'.format() 或 '%s'%videoName    # print(urlData)    for line in urlData:        # 解码,由于是直接使用了所抓取的链接内容,所以需要按行解码,如果提前解码则不能使用直接进行for循环,会报错        # 改用上面的readlines()或readline()也可以,但更繁琐些,同样需要按行解码,效率更低        url_ts = line.decode('utf-8')        tempName_ts = os.path.join(path, f'{num}.ts')  # f'{}' 相当于'{}'.format()        if not '.ts' in url_ts:            continue        else:            if not url_ts.startswith('http'):  # 判断字符串是否以'http'开头,如果不是则说明url链接不完整,需要拼接                # 拼接ts流视频的url                url_ts = url_m3u8.replace(url_m3u8.split('/')[-1], url_ts)        print(url_ts)        getDown_urllib(url_ts, tempName_ts)  # 下载视频流        if num == 0:            # 重命名,已存在则自动覆盖            shutil.move(tempName_ts, tempName_video)            num += 1            continue        cmd = f'copy /b {tempName_video}+{tempName_ts} {tempName_video}'        res = os.system(cmd)        if res == 0:            os.system(f'del {tempName_ts}')            if num == 20:  # 限制下载的ts流个数,这个视频挺长有四百多个.ts文件,所以限制一下                break            num += 1            continue        print(f'Wrong, copy {num}.ts-->{videoName}.ts failure')        return False    os.system(f'del {path}/*.ts')  # 调用windows命令行(即cmd)工具,运行命令    filename = os.path.join(path, f'{videoName}.mp4')    shutil.move(tempName_video, filename)    print(f'{videoName}.mp4 finish down!')if __name__ == '__main__':    url_m3u8 = 'http://wscdn.alhls.xiaoka.tv/201886/2f5/75a/HoHdTc1LjUaBjZbJ/index.m3u8'    path = r'D:\videos'    videoName = url_m3u8.split('/')[-2]    getVideo_urllib(url_m3u8, path, videoName)​

  

注:修改文件名时,特意选择shutil模块(可以看作操作系统的高级版)的移动方法,虽然移动主要是用来移动文件的,重命名算是附带的,不过强制覆盖的特点在这里很有用,避免中断后重新下载时重命名产生异常。

PS:说来有趣,7月31号,也就是离职的那天上午,灵感突显,利用请求下载文件的写入特点,彻底解决了调用命令行导致的不兼容的窗口以外环境的问题,哈哈,所以下一篇就它了。

转载于:https://www.cnblogs.com/guyuecanwu/p/9502230.html

你可能感兴趣的文章
几句话总结一个算法之Policy Gradients
查看>>
搬家来博客园了
查看>>
Asp.net MVC Global.asax文件
查看>>
Tomcat工作原理
查看>>
中石油 1380 森林扩张
查看>>
为什么研发团队不适合量化KPI的绩效考核?
查看>>
HDU - 4725 The Shortest Path in Nya Graph(拆点+Dijkstra)
查看>>
不要完全相信Chrome控制台打印的信息
查看>>
1.openshift搭建
查看>>
实例探索Class文件
查看>>
hdu 3466 Proud Merchants
查看>>
三个绘图工具类详解
查看>>
使用Delphi对象(声明、实例化、构造、释放)
查看>>
触发器
查看>>
ASP.NET Core 2.1的配置、AOP、缓存、部署、ORM、进程守护、Nginx、Polly【源码】
查看>>
HDU 1195 Open the lock
查看>>
git简单获取远程某个分支代码命令
查看>>
HDU_1245_Saving James Bond_最短路
查看>>
hdu 2459 Maximum repetition substring(后缀数组)
查看>>
2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor(LCA+K级父亲暴力卡过)
查看>>