python爬取网站m3u8视频,将ts解密成mp4,合并成整体视频

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/a33445621/article/details/80377424

一些网站会提供m3u8视频地址,以供下载观看。或者一些网站经过分析后发现是使用m3u8格式进行播放的,这时使用m3u8的地址链接就可以下载到相应的视频。


一、关于m3u8:(https://blog.csdn.net/baidu_34418350/article/details/64922512)

m3u8是苹果公司推出一种视频播放标准,是m3u的一种,不过 编码方式是utf-8,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少I/o访问次数,一般存在服务器的内存中),通过m3u8解析出来路径,然后去请求。

示例链接:http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/rexuechangan01.m3u8

第一层

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2650800,RESOLUTION=1920x1080
1.m3u8

观察数据吗,没有用http://开头时,不是真正路径,需要拼接字符串再次请求: http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/1.m3u8  得到数据

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:14
#EXTINF:11.480, 
20170215T224129-1-0.ts
#EXTINF:11.480, 
20170215T224129-1-1.ts
#EXTINF:10.480, 
20170215T224129-1-2.ts
#EXTINF:11.400, 
20170215T224129-1-3.ts
#EXTINF:11.120, 

20170215T224129-1-4.ts

。。。

#EXTINF:1.000000,
3RCP49g82011159.ts
#EXTINF:0.600000,
3RCP49g82011160.ts

#EXT-X-ENDLIST

看到ts结尾的文件,这才是视频真正的存放路径:

http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/20170215T224129-1-0.ts 

这时候用浏览器下载就可以播放。不过这个播放不用我们去解析 android 4.0以后的videoView 就支持自动解析,并拼接播放。

安卓代码:

	Uri uri = Uri.parse("http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/rexuechangan01.m3u8");
	video_view.setMediaController(new MediaController(this));
	video_view.setVideoURI(uri);
	video_view.requestFocus();
	ideo_view.start();
	这样就可以简单的播放M3u8格式的视频了。


下载到本地,可直接用视频软件打开:




二、视频下载

可以用python脚本自动下载这些ts文件,但实际上有些网站的ts文件是用AES-128加密过的,所以需要解密才能播放。

加密过的视频在第二层m3u8中会有一个key文件链接:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0

#EXT-X-KEY:METHOD=AES-128,URI="key.key"  #key密钥文件

需要去读取这个key文件,才能拿到解密密钥。


    
    
  1. # -*- coding:utf-8 -*-
  2. import os
  3. import sys
  4. import requests
  5. import datetime
  6. from Crypto.Cipher import AES
  7. from binascii import b2a_hex, a2b_hex
  8. reload(sys)
  9. sys.setdefaultencoding( 'utf-8')
  10. def download(url):
  11. download_path = os.getcwd() + "\download"
  12. if not os.path.exists(download_path):
  13. os.mkdir(download_path)
  14. #新建日期文件夹
  15. download_path = os.path.join(download_path, datetime.datetime.now().strftime( '%Y%m%d_%H%M%S'))
  16. #print download_path
  17. os.mkdir(download_path)
  18. all_content = requests.get(url).text # 获取第一层M3U8文件内容
  19. if "#EXTM3U" not in all_content:
  20. raise BaseException( "非M3U8的链接")
  21. if "EXT-X-STREAM-INF" in all_content: # 第一层
  22. file_line = all_content.split( "\n")
  23. for line in file_line:
  24. if '.m3u8' in line:
  25. url = url.rsplit( "/", 1)[ 0] + "/" + line # 拼出第二层m3u8的URL
  26. all_content = requests.get(url).text
  27. file_line = all_content.split( "\n")
  28. unknow = True
  29. key = ""
  30. for index, line in enumerate(file_line): # 第二层
  31. if "#EXT-X-KEY" in line: # 找解密Key
  32. method_pos = line.find( "METHOD")
  33. comma_pos = line.find( ",")
  34. method = line[method_pos:comma_pos].split( '=')[ 1]
  35. print "Decode Method:", method
  36. uri_pos = line.find( "URI")
  37. quotation_mark_pos = line.rfind( '"')
  38. key_path = line[uri_pos:quotation_mark_pos].split( '"')[ 1]
  39. key_url = url.rsplit( "/", 1)[ 0] + "/" + key_path # 拼出key解密密钥URL
  40. res = requests.get(key_url)
  41. key = res.content
  42. print "key:" , key
  43. if "EXTINF" in line: # 找ts地址并下载
  44. unknow = False
  45. pd_url = url.rsplit( "/", 1)[ 0] + "/" + file_line[index + 1] # 拼出ts片段的URL
  46. #print pd_url
  47. res = requests.get(pd_url)
  48. c_fule_name = file_line[index + 1].rsplit( "/", 1)[ -1]
  49. if len(key): # AES 解密
  50. cryptor = AES.new(key, AES.MODE_CBC, key)
  51. with open(os.path.join(download_path, c_fule_name + ".mp4"), 'ab') as f:
  52. f.write(cryptor.decrypt(res.content))
  53. else:
  54. with open(os.path.join(download_path, c_fule_name), 'ab') as f:
  55. f.write(res.content)
  56. f.flush()
  57. if unknow:
  58. raise BaseException( "未找到对应的下载链接")
  59. else:
  60. print "下载完成"
  61. merge_file(download_path)
  62. def merge_file(path):
  63. os.chdir(path)
  64. cmd = "copy /b * new.tmp"
  65. os.system(cmd)
  66. os.system( 'del /Q *.ts')
  67. os.system( 'del /Q *.mp4')
  68. os.rename( "new.tmp", "new.mp4")
  69. if __name__ == '__main__':
  70. url = "http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/rexuechangan01.m3u8"
  71. download(_url)


三、关于解密报错:No module named Crypto.Cipher

在python 中使用AES算法时,会报告上述错误,原因是Crypto并非标准模块,需要自己单独安装。

from Crypto.Cipher import AES
    
    

第一种办法:pip install pycropt 如果报错,就选择第二种办法。

第二种办法:使用编译好的安装包。http://www.voidspace.org.uk/python/modules.shtml#pycrypto

装上不好使就换一个试试,安装上面2个都不好使,就安装低版本的(我本机安装上面2个都报错,安装下面的版本就可用了)


如果还是报错就到下面目录修改大小写:(我没遇到这个问题)

C:\Python27\Lib\site-packages\crypto 改成

 C:\Python27\Lib\site-packages\Crypto


四、合并文件

可以通过cmd命令的方式将所有的ts合并成一个文件:

copy /b d:\xxx\download_ts\*   d:\xxx\download_ts\new.mp4

直接调用merge_file即可,会删除临时文件

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值