上海保洁服务网站建设,xampp里wordpress安装教程,wordpress dux添加统计代码,页面设计及逻辑方案M3U8流视频数据爬虫
HLS技术介绍
现在大部分视频客户端都采用HTTP Live Streaming#xff08;HLS#xff0c;Apple为了提高流播效率开发的技术#xff09;#xff0c;而不是直接播放MP4等视频文件。HLS技术的特点是将流媒体切分为若干【TS片段】#xff08;比如几秒一段…M3U8流视频数据爬虫
HLS技术介绍
现在大部分视频客户端都采用HTTP Live StreamingHLSApple为了提高流播效率开发的技术而不是直接播放MP4等视频文件。HLS技术的特点是将流媒体切分为若干【TS片段】比如几秒一段然后通过一个【M3U8列表文件】将这些TS片段批量下载供客户端播放器实现实时流式播放。因此在爬取HLS的流媒体文件的思路一般是先【下载M3U8文件】并分析其中内容然后在批量下载文件中定义的【TS片段】最后将其【组合】成mp4文件或者直接保存TS片段。
M3U8文件详解
如果想要爬取HLS技术下的资源数据首先要对M3U8的数据结构和字段定义非常了解。M3U8是一个扩展文件格式由M3U扩展而来。那么什么是M3U呢
M3U文件
M3U这种文件格式本质上说不是音频视频文件它是音频视频文件的列表文件是纯文本文件。
M3U这种文件被获取后播放软件并不是播放它而是根据它的记录找到媒体的网络地址进行在线播放。也就是说M3U格式的文件只是存储多媒体播放列表并提供了一个指向其他位置的音频视频文件的索引播放的是那些被指向的文件。
为了能够更好的理解M3U的概念我们先简单做一个M3U文件myTest.m3u。在电脑中随便找几个MP3MP4文件依次输入这些文件的路径myTest.m3u文件内容如下
E:\Users\m3u8\刘德华 - 无间道.mp4
E:\Users\m3u8\那英 - 默.mp3
E:\Users\m3u8\周杰伦 - 不能说的秘密.mp4
E:\Users\m3u8\花粥 - 二十岁的某一天.mp3
E:\Users\m3u8\周深 - 大鱼.mp4M3U8文件
M3U8也是一种M3U的扩展格式高级的M3U所以也属于M3U。
**M3U8示例**大家会看到在该文件中有大量的ts文件的链接地址这个就是我们之前描述的真正的视频文件。其中任何一个ts文件都是一小段视频可以单独播放。我们做视频爬虫的目标就是把这些ts文件都爬取下来。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:3.127,
/20230512/RzGw5hDB/1500kb/hls/YZefAiEF.ts
#EXTINF:3.127,
/20230512/RzGw5hDB/1500kb/hls/FsliUCL6.ts
#EXTINF:3.127,
/20230512/RzGw5hDB/1500kb/hls/DD7c47bz.ts
#EXT-X-ENDLIST实战
需求
https://www.mjtt5.tv/
具体操作
进入视频播放页点击播放按钮定位ts数据包从中提取ts片段的url探究url的规律打开抓包工具刷新页面全局搜索m3u8定位到找到m3u8文件解析m3u8文件提取文件中ts片段链接
同步操作代码
import requests
from urllib.parse import urljoin
import re
import os
dirName tsLib
if not os.path.exists(dirName):os.mkdir(dirName)headers {User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
}
#m3u8地址
url https://cdn13.tvtvgood.com/202310/20/c1959422deee/playlist.m3u8?tokend5i9GCr3ljqGsSf48-aG2wexpires1698221543
page_text requests.get(urlurl,headersheaders).text
page_text page_text.strip()#解析出每一个ts切片的地址
ts_url_list []
for line in page_text.split(\n):if not line.startswith(#):ts_url line#不同ts下载地址ts_url https://cdn13.tvtvgood.com/202310/20/c1959422deee/ts_urlts_url_list.append(ts_url)print(ts_url_list)
#请求到每一个ts切片的数据
for url in ts_url_list:#获取ts片段的数据ts_data requests.get(urlurl,headersheaders).contentts_name url.split(/)[-1]ts_path dirName/ts_namewith open(ts_path,wb) as fp:#需要将解密后的数据写入文件进行保存fp.write(ts_data)print(ts_name,下载保存成功)# ts文件的合并最好网上找专业的工具进行合并自己手动合并会经常出问题异步操作代码协程
#https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/playlist8.ts
#https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/playlist7.ts
import requests
import os
import asyncio
import aiohttp
from threading import Thread
dirName tsLib
if not os.path.exists(dirName):os.mkdir(dirName)headers {User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
}
#m3u8文件的url
m3u8_file_url https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/playlist.m3u8?token9vVIuesP2MAZ4G1V6y6DnAexpires1698927688
m3u8_text requests.get(urlm3u8_file_url,headersheaders).textts_url_list [] #存储解析出来的每一个ts片段的url
for line in m3u8_text.split(\n):if not line.startswith(#):ts_url linets_url https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/ts_urlts_url_list.append(ts_url)#基于协程实现异步的ts片段的请求
async def get_reqeust(url):#参数url就是ts片段的请求urlasync with aiohttp.ClientSession() as req:async with await req.get(urlurl,headersheaders) as response:ts_data await response.read()dic {ts_data:ts_data,ts_title:url.split(/)[-1]}return dicdef save_ts_data(t):dic t.result()ts_data dic[ts_data]ts_title dic[ts_title]ts_path dirName / ts_titlewith open(ts_path,wb) as fp:fp.write(ts_data)print(ts_title,保存下载成功)tasks []
for url in ts_url_list:c get_reqeust(url)task asyncio.ensure_future(c)task.add_done_callback(save_ts_data)tasks.append(task)loop asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))#使用协程实现一定得有一个url列表遍历该列表进行多协程的创建
#使用多个loop的场景两种数据资源下载需要实现有两个url列表
#问题两个loop之间的关系是异步的吗
#注意千万别搞loop的嵌套。#特殊的方式创建两个线程两个线程中封装处理两个loop。线程池的实现方案
#https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/playlist8.ts
#https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/playlist7.ts
import requests
import os
from threading import Thread
from multiprocessing.dummy import PooldirName tsLib
if not os.path.exists(dirName):os.mkdir(dirName)headers {User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36,Connection:closed
}
#m3u8文件的url
m3u8_file_url https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/playlist.m3u8?token9vVIuesP2MAZ4G1V6y6DnAexpires1698927688
m3u8_text requests.get(urlm3u8_file_url,headersheaders).textts_url_list [] #存储解析出来的每一个ts片段的url
for line in m3u8_text.split(\n):if not line.startswith(#):ts_url linets_url https://cdn8.tvtvgood.com/202206/21/6abfb3237d01/ts_urlts_url_list.append(ts_url)def get_reqeust(url):#参数url就是ts片段的请求urlts_data requests.get(urlurl,headersheaders,verifyFalse).contentts_path dirName / url.split(/)[-1]with open(ts_path,wb) as fp:fp.write(ts_data)print(ts_path,:保存下载成功)#HTTPSConnectionPool异常原因#网络请求的并发量太大减少并发or在headers中添加一个Connection:closedpool Pool(100)
pool.map(get_reqeust,ts_url_list)