新用户注册入口 老用户登录入口

[转载]练习:《斗鱼视频》m3u8流视频采集下载+思路+Python

文章作者:转载 更新时间:2023-12-18 11:34:00 阅读数量:118
文章标签:斗鱼视频下载ts文件手机端接口合并抓包分析
本文摘要:这篇文章详细介绍了通过抓包分析斗鱼视频链接,发现并利用手机端接口获取playlist.m3u8文件地址,进而批量下载.ts片段的方法。针对PC端签名(sign)问题,文章提出了有效解决方案,并通过Python实现合并.ts文件为完整视频的流程。同时,使用MongoDB进行存储管理以过滤重复下载。整个过程中涉及的关键技术点包括:斗鱼视频、下载、playlist.m3u8、.ts文件、签名(sign)、手机端接口、合并、Python实现、抓包分析及MongoDB存储。
转载文章

本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_35875470/article/details/89857445。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

首先感谢以下大佬提供帮助

  1. 斗鱼视频下载-> https://www.jianshu.com/p/feccccb097be
  2. 批量合并处理B站视频->https://www.wandouip.com/t5i227224/
  3. You-Get->https://you-get.org/

思路

  • 首先打开了PC端斗鱼视频一个链接:https://v.douyu.com/show/0Q8mMY0xXDL749Ad
  • 发现一个参数在链接中 0Q8mMY0xXDL749Ad
  • 通过抓包发现了一个很重要的文件:playlist.m3u8
    1. 里面包含了数个 .ts 的网络地址;
    1. .ts 文件是可以播放的视频片段;
    1. 发现 可以通过合并 .ts 片段可以得到完整视频;
  • 出现一个问题:playlist.m3u8 怎么获取?
    1. 发现:https://v.douyu.com/api/stream/getStreamUrl 可以获取 playlist.m3u8 文件地址;
    1. 需要POST传入一些参数才行,发现: sign 参数是一种签名,一般通过JS生成,找了半天没有方法生成 sign 参数;
    1. 通过查阅大佬文献发现:手机端的斗鱼视频有接口可以直接获取 playlist.m3u8 文件地址,成功越过 sign 签名防线;
  • 手机端斗鱼视频链接:https://vmobile.douyu.com/show/0Q8mMY0xXDL749Ad
    1. 通过抓包发现:https://vmobile.douyu.com/video/getInfo?vid=0Q8mMY0xXDL749Ad;
    1. 这就解决了playlist.m3u8 文件获取问题:json[‘data’][‘video_url’] 第一个难题解决!!;

综上所述,整理一下具体采集流程:

  1. 获取vid = 0Q8mMY0xXDL749Ad (就是链接中的参数);
  2. 通过 https://vmobile.douyu.com/video/getInfo?vid=0Q8mMY0xXDL749Ad 获取 playlist.m3u8 文件地址;
  3. 解析 playlist.m3u8 文件提取所有 .ts文件;
  4. 下载所有 .ts 文件;
  5. 合并 .ts 成视频文件输出;

Python实现

  1. 不要开启线程池,因为会有一些问题

app.py
config 中可以配置

import requests
import re
import json
import time
import pymongo
import psutil
from hashlib import md5
from moviepy.editor import *
from multiprocessing import Pool#基本配置
config = {'UID':'gKpdxKRWXwaW',#用户ID'CID':104,#栏目ID'TYPE':1, #1=>按用户id采集列表,2=>按栏目ID采集列表'TIME_START':1,#起始时间'TIME_ENT':500,#结束时间'PAGE_START':1,#起始页'PAGE_END':10,#结束页'TIME_GE':0,#每个下载间隔时间'POOL':False,#是否开启线程池'CHECKID':True, #True 过滤已经下载过的视频 False 不过滤'FILE_PATH':'F:/ceshi/',#下载目录,【会自动创建文件夹】'TS_PATH':'F:/ceshi/download/',#缓存文件目录,【会自动创建文件夹】'DB_URL':'localhost',#数据库地址'DB_NAME':'douyu',#数据库名称''DB_TABLE':'douyu'#数据库表
}#MongoDB初始化
client = pymongo.MongoClient(config['DB_URL'])
mango_db = client[config['DB_NAME']]#MongoDB存储
def save_to_mango(result):if mango_db[config['DB_TABLE']].insert_one({'vid':result}):print('成功存储到MangoDB')return Truereturn False
#MongoDB验证重复
def check_to_mongo(vid):count = mango_db[config['DB_TABLE']].find({'vid':vid}).count()if count==0:return Falsereturn True#删除文件
def del_file(page):if os.path.exists(page):# 删除文件,可使用以下两种方法。os.remove(page)# os.unlink(my_file)else:print('no such file:%s' % page)#循环列表删除文件
def loop_del_file(arr):for item in arr:del_file(item)#请求器
def get_content_requests(url):headers = {}headers['user-agent']='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'headers['cookie'] = 'dy_did=07f83a57d1d2e22942e0883200001501; acf_did=07f83a57d1d2e22942e0883200001501; Hm_lvt_e99aee90ec1b2106afe7ec3b199020a7=1556514266,1557050422,1557208315; acf_auth=; acf_auth_wl=; acf_uid=; acf_nickname=; acf_username=; acf_own_room=; acf_groupid=; acf_notification=; acf_phonestatus=; _dys_lastPageCode=page_video,page_video; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=1557209469; _dys_refer_action_code=click_author_video_cate2'try:req_content = requests.get(url,headers = headers)if req_content.status_code == 200:return req_contentprint('请求失败:',url)return Noneexcept:print('请求失败:', url)return None#把时间换算成秒
def str_to_int(time):try:time_array = time.split(':')time_int = (int(time_array[0])*60)+int(time_array[1])return time_intexcept:print('~~~~~计算视频时间失败~~~~~')return None#提取需要采集的数据
def get_list(html,type = 1):data = []try:list_json = json.loads(str(html))for om in list_json['data']['list']:gtime = str_to_int(om['video_str_duration'])if gtime > config['TIME_START'] and gtime < config['TIME_ENT']:if type == 2:data.append({'title': om['title'], 'vid': om['url'].split('show/')[1]})else:data.append({'title': om['title'], 'vid': om['hash_id']})return dataexcept:print('~~~~~数据提取失败~~~~~')return None#解析playlist.m3u8
def get_ts_list(m3u8):data = []try:html_m3u8_json = json.loads(m3u8)m3u8_text = get_content_requests(html_m3u8_json['data']['video_url'])m3u8_vurl =html_m3u8_json['data']['video_url'].split('playlist.m3u8?')[0]if m3u8_text:get_text = re.findall(',\n(.*?).ts(.*?)\n#',m3u8_text.text,re.S)for item in get_text:data.append(m3u8_vurl+item[0]+'.ts'+item[1])return datareturn Noneexcept:print('~~~~~解析playlist.m3u8失败~~~~~')return None# 杀死moviepy产生的特定进程
def killProcess():# 处理python程序在运行中出现的异常和错误try:# pids方法查看系统全部进程pids = psutil.pids()for pid in pids:# Process方法查看单个进程p = psutil.Process(pid)# print('pid-%s,pname-%s' % (pid, p.name()))# 进程名if p.name() == 'ffmpeg-win64-v4.1.exe':# 关闭任务 /f是强制执行,/im对应程序名cmd = 'taskkill /f /im ffmpeg-win64-v4.1.exe  2>nul 1>null'# python调用Shell脚本执行cmd命令os.system(cmd)except:pass#下载.ts文件
def download_ts(m3u8_list,name):try:if not os.path.exists(config['FILE_PATH']):os.makedirs(config['FILE_PATH'])if not os.path.exists(config['TS_PATH']):os.makedirs(config['TS_PATH'])if os.path.exists(config['FILE_PATH']+name+'.mp4'):name = name+'_'+str(int(time.time()))print('开始下载:',name)L = []R = []for p in m3u8_list:ts_find = get_content_requests(p)file_ts = '{0}{1}.ts'.format(config['TS_PATH'],md5(ts_find.content).hexdigest())with open(file_ts,'wb') as f:f.write(ts_find.content)R.append(file_ts)hebing = VideoFileClip(file_ts)L.append(hebing)killProcess()print('下载完成:',file_ts)mp4file = '{0}{1}.mp4'.format(config['FILE_PATH'],name)final_clip = concatenate_videoclips(L)final_clip.to_videofile(mp4file, fps=24, remove_temp=True)killProcess()loop_del_file(R)print('\n下载完成:',name)print('')return Trueexcept:print('~~~~~合成.ts文件失败~~~~~')return None#下载视频列表
def list_get_kong(list_json):for item in list_json:y = Trueif config['CHECKID']:if check_to_mongo(item['vid']):print('~~~~~检测到重复项~~~~~')y = Falseif y:get_show_html = get_content_requests('https://vmobile.douyu.com/video/getInfo?vid=' + item['vid'])if get_show_html:m3u8_list = get_ts_list(get_show_html.text)if m3u8_list:download = download_ts(m3u8_list, item['title'])if download: save_to_mango(item['vid'])time.sleep(config['TIME_GE'])#控制器
def main(page):if config['TYPE']==1:print('~~~~~按用户ID采集~~~~~')listurl = 'https://v.douyu.com/video/author/getAuthorVideoListByNew?up_id={0}&cate2_id=0&limit=30&page={1}'.format(config['UID'],page)get_list_html = get_content_requests(listurl)if get_list_html:list_json = get_list(get_list_html.text,1)if list_json:list_get_kong(list_json)else:print('~~~~~按列表ID采集~~~~~')listurl = 'https://v.douyu.com/video/video/listData?page={1}&cate2Id={0}&action=new'.format(config['CID'],page)get_list_html = get_content_requests(listurl)if get_list_html:list_json = get_list(get_list_html.text,2)if list_json:list_get_kong(list_json)#初始化
if __name__=='__main__':if config['POOL']:groups = [x for x in range(config['PAGE_START'],config['PAGE_END']+1)]pool = Pool()pool.map(main, groups)else:for item in range(config['PAGE_START'],config['PAGE_END']+1):main(item)print('~~~~~已经完成【所有操作】~~~~~')

总结:众所周知,BiliBili是一个学习的网站!

本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_35875470/article/details/89857445。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

相关阅读
文章标题:[转载][洛谷P1082]同余方程

更新时间:2023-02-18
[转载][洛谷P1082]同余方程
文章标题:[转载]webpack优化之HappyPack实战

更新时间:2023-08-07
[转载]webpack优化之HappyPack实战
文章标题:[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法

更新时间:2023-09-10
[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法
文章标题:[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo

更新时间:2024-03-11
[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo
文章标题:[转载]程序员也分三六九等?等级差异,一个看不起一个!

更新时间:2024-05-10
[转载]程序员也分三六九等?等级差异,一个看不起一个!
文章标题:[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集

更新时间:2024-01-12
[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集
名词解释
作为当前文章的名词解释,仅对当前文章有效。
playlist.m3u8playlist.m3u8是一种基于HTTP Live Streaming (HLS)协议的媒体播放列表文件格式,通常用于流媒体服务中。在本文语境下,斗鱼视频将其用于存储一个视频流的所有.ts片段(视频切片)的网络地址清单。当客户端(如浏览器或播放器)请求播放某个直播或点播视频时,会首先获取到playlist.m3u8文件,根据其中列出的地址顺序下载并连续播放.ts片段,从而实现视频流的无缝播放。
ts文件.ts文件是MPEG-2 Transport Stream(传输流)文件格式,常用于数字电视广播、DVD和在线流媒体服务中存储音频和视频数据。在本文中,斗鱼视频将完整的视频内容分割成多个.ts片段进行存储和传输。每个.ts文件包含一小段连续的音视频数据,通过合并这些.ts片段可以重构原始的完整视频。
MongoDBMongoDB是一个开源的、面向文档的NoSQL数据库系统,适用于大规模数据存储和处理场景。在文章所给出的Python代码实现中,MongoDB被用来存储已经下载过的斗鱼视频信息,以避免重复下载。其灵活的数据模型允许开发者以JSON-like文档的形式存储数据,并提供了丰富的查询语言和高可用性特征,使得在整个采集流程中能够方便地对数据进行增删查改等操作。例如,在文中提到的`save_to_mango`函数中,就使用了MongoDB来存储抓取到的斗鱼视频ID,以便后续检查是否已下载过该视频。
延伸阅读
作为当前文章的延伸阅读,仅对当前文章有效。
在了解了如何通过抓包分析和Python编程技术实现斗鱼视频的批量下载后,对于流媒体视频技术和网络爬虫领域的延伸阅读推荐如下:
近期,《中国网络安全》杂志发布了一篇深度报道,探讨了随着流媒体直播行业的快速发展,视频资源防盗链及反爬机制的重要性。文中提到,各大直播平台如斗鱼、虎牙等都在不断强化其内容保护措施,采用动态签名、加密传输等多种技术手段来防止非法下载和传播。这也对合法合规的数据采集与分析提出了更高要求,研究者和开发者必须熟悉并遵守相关法律法规,在确保知识产权不受侵犯的同时,寻求更高效、安全的技术解决方案。
同时,开源社区GitHub上出现了不少针对各类直播平台优化的视频下载工具项目,这些项目不仅实现了对.ts文件片段的智能解析和合并,还有的开始探索基于机器学习的方法来预测和模拟签名算法,以适应日益严格的反爬策略。例如,“Streamlink”是一款跨平台的命令行实用程序,能够从各种受保护的流媒体网站中提取并播放视频流,为研究人员提供了合法获取和处理流媒体数据的新思路。
此外,国家版权局近年来也加大了对网络侵权盗版行为的打击力度,并呼吁广大网民自觉抵制非法下载和传播他人作品的行为,倡导尊重原创、保护版权的社会风尚。在实际操作中,开发者应关注《信息网络传播权保护条例》等相关法规,确保个人或团队的研究活动既满足学术探究需求,又符合法律规定。
总之,面对流媒体视频下载与处理这一领域,我们既要掌握先进的技术方法以适应日新月异的网络环境,又要时刻保持对法律边界的敬畏之心,做到技术发展与法制建设相得益彰。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
pgrep process_pattern - 根据进程名模式搜索进程ID。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
HessianRPC在高负载下服务降级与熔断器模式保障用户体验 05-01 jQuery和TweenMax简单实用的水平手风琴特效 01-20 jquery选择国家下拉列表框插件 01-21 Sqoop在Hadoop集群中的数据传输机制及数据库迁移、收集与备份恢复应用实践 12-23 简约渔具批发牧渔企业类网站前端模板下载 11-09 基于bootstrap功能齐全的jQuery进度条插件 10-20 简约大气男性护肤产品HTML5网站模板 09-22 宽屏大气机械设备制造公司网站模板 08-13 演讲会门票销售网站模板下载 07-30 本次刷新还10个文章未展示,点击 更多查看。
经典响应式投资理财企业前端模板 06-26 基于Redis的键值对存储实现用户阅读状态跟踪与管理 06-24 Netty框架中CannotFindServerSelection异常:服务器地址配置错误与通道类型匹配详解 06-18 简洁设计公司响应式网站模板下载 05-06 绿色苗木草坪种植绿化类企业前端CMS模板下载 04-30 怎么在cmd开启mysql服务 04-15 保洁公司家庭保洁服务网站模板 03-26 SpringCloud微服务中分布式锁的死锁问题与状态一致性维护:避免循环依赖、公平锁及超时重试机制在Redisson中的实践运用 03-19 HBase性能测试与RegionServer配置、架构及数据模型调优实践:关注响应时间、并发处理能力与BlockCache优化 03-14 jquery控制radio触发事件 02-15 简约HTML5软件营销业务公司网站模板 02-09
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"