ToB企服应用市场:ToB评测及商务社交产业平台

标题: 从【抓包分析】到【代码实战】,实现下载某破站视频(附源码) [打印本页]

作者: 写过一篇    时间: 2023-11-14 13:42
标题: 从【抓包分析】到【代码实战】,实现下载某破站视频(附源码)
一、前言

前两天,我的邻居找到我,问我某破站的视频能否帮她下载成mp4格式?
网上应该有很多的下载工具,但是如果直接让她网上找,那么无法彰显我程序员大神的威武形象。因此我回复她,程序员大神是无敌的,只要在浏览器上能看到的东西,都能用程序拿到。只要在浏览器上用手能操作的东西,都能用程序操作。只要......
我发现我的邻居,已经悄然成为了我的产品经理,这些年着实给我提了不少产品思路哈哈哈。
二、需求分析

其实要做的功能,非常简单。从某破站上打开一个视频,从浏览器地址栏拿到这个视频的地址,然后粘贴到我开发的程序中,程序自动将相应的视频下载下来变成mp4格式。
干脆,我把程序放到我的云服务器上,这样不但邻居可以使用,世界各地的美女帅哥都能使用。如果用的人多了,我给他变成收费模式,下载一个视频收1分钱,一天如果有1万个人下载,不就能收100元吗?一个月30天,那就是3万,一年365天,那就是365*3万=1095万,艾玛这是要发大财呀。
你看,我不止是程序员大神,还是数学大神。其实数学十分简单,只不过剩下的九十分很难。
三、抓包分析

1、拿到视频文件真实地址

我们进入某破站,随便打开一个视频,咱们就用浏览器自带的网络监控工具抓包。
好家伙,这一大堆请求,一直在不停地刷,放个图大家感受一下:

不过凭借程序员大神多年的经验,直觉告诉我,咱们重点关注这俩请求:

看一下这俩请求的应答内容,这一看就是我们要的视频二进制内容嘛:

等等!1267024297-1-100024.m4s和1267024297-1-30232.m4s这些数字是从哪里来的呢?看起来像是视频的ID号之类的,但是浏览器链接栏中也没看到类似的号呢?
那接下来咱先看看第一个请求吧,看这里面能否找到啥蛛丝马迹。
这第一个请求就是我点击视频链接后发出的,这和浏览器地址栏的地址是一致的:

再看一下这个请求的应答是啥内容:

应答就是一段标准的html嘛。看看这里面有没有1267024297-1-100024.m4s和1267024297-1-30232.m4s相关的内容呢?搜一下,果然找到了:

看起来就是一段json,下面我把这段json贴出来,内容太多,我稍微删减了一些,只留下关键信息:
查看代码
  1.  
复制代码
所以,我们第一步的思路就有了:请求视频地址,然后将应答中的这段json拿出来,再从json中将视频文件真实地址拿到。
2、下载视频文件

我们看上面的json,data.dash.video路径下面的值,就是我们要下载的视频的真实地址,但我们看到这是个Array,也就是说有多个视频地址,我们下载哪一个呢?我测试了一下,把所有视频都下载下来,视频内容都是一致的,只不过文件大小、视频长宽、码率之类的不同,我估计对应的是"高清 1080P+", "高清 1080P", "高清 720P", "清晰 480P", "流畅 360P"之类的。我们就简单处理吧,默认下载第一个视频就行了。
下面咱看看第一个视频的具体信息:
查看代码
  1.  {
  2.     "id": 80,
  3.     "baseUrl": "https://xy182x117x194x4xy.mcdn.xxxxxxxxxx.cn:8082/v1/resource/1267024297-1-100113.m4s?agrr=0&build=0&buvid=423719E5-C1F3-8E99-9949-C4F0FD92681D98687infoc&bvc=vod&bw=107051&deadline=1695874583&e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D&f=u_0_0&gen=playurlv2&logo=A0000400&mcdnid=11000413&mid=1716139964&nbs=1&nettype=0&oi=3550958494&orderid=0%2C3&os=mcdn&platform=pc&sign=20f269&traceid=trDNtOvronEayd_0_e_N&uipk=5&uparams=e%2Cuipk%2Cnbs%2Cdeadline%2Cgen%2Cos%2Coi%2Ctrid%2Cmid%2Cplatform&upsig=b33a062d8cc1d08690ad8f7d727e5a1f",
  4.     "base_url": "https://xy182x117x194x4xy.mcdn.xxxxxxxxxx.cn:8082/v1/resource/1267024297-1-100113.m4s?agrr=0&build=0&buvid=423719E5-C1F3-8E99-9949-C4F0FD92681D98687infoc&bvc=vod&bw=107051&deadline=1695874583&e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M%3D&f=u_0_0&gen=playurlv2&logo=A0000400&mcdnid=11000413&mid=1716139964&nbs=1&nettype=0&oi=3550958494&orderid=0%2C3&os=mcdn&platform=pc&sign=20f269&traceid=trDNtOvronEayd_0_e_N&uipk=5&uparams=e%2Cuipk%2Cnbs%2Cdeadline%2Cgen%2Cos%2Coi%2Ctrid%2Cmid%2Cplatform&upsig=b33a062d8cc1d08690ad8f7d727e5a1f",
  5.     "backupUrl": ["https://xy112x111x47x2xy.mcdn.xxxxxxxxxx.cn:4483/upgcxcode/07/13/1267024297/1267024297-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1695874583&gen=playurlv2&os=mcdn&oi=3550958494&trid=00001a6a4eb478e4473c92669eaa7931691bu&mid=1716139964&platform=pc&upsig=b33a062d8cc1d08690ad8f7d727e5a1f&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&mcdnid=11000413&bvc=vod&nettype=0&orderid=0,3&buvid=423719E5-C1F3-8E99-9949-C4F0FD92681D98687infoc&build=0&f=u_0_0&agrr=0&bw=107051&logo=A0000400", "https://upos-sz-mirrorali.xxxxxxxxxx.com/upgcxcode/07/13/1267024297/1267024297-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1695874583&gen=playurlv2&os=alibv&oi=3550958494&trid=1a6a4eb478e4473c92669eaa7931691bu&mid=1716139964&platform=pc&upsig=7b626b942dab4437433e276e1dfd6c63&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=1,3&buvid=423719E5-C1F3-8E99-9949-C4F0FD92681D98687infoc&build=0&f=u_0_0&agrr=0&bw=107051&logo=40000000"],
  6.     "backup_url": ["https://xy112x111x47x2xy.mcdn.xxxxxxxxxx.cn:4483/upgcxcode/07/13/1267024297/1267024297-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1695874583&gen=playurlv2&os=mcdn&oi=3550958494&trid=00001a6a4eb478e4473c92669eaa7931691bu&mid=1716139964&platform=pc&upsig=b33a062d8cc1d08690ad8f7d727e5a1f&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&mcdnid=11000413&bvc=vod&nettype=0&orderid=0,3&buvid=423719E5-C1F3-8E99-9949-C4F0FD92681D98687infoc&build=0&f=u_0_0&agrr=0&bw=107051&logo=A0000400", "https://upos-sz-mirrorali.xxxxxxxxxx.com/upgcxcode/07/13/1267024297/1267024297-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1695874583&gen=playurlv2&os=alibv&oi=3550958494&trid=1a6a4eb478e4473c92669eaa7931691bu&mid=1716139964&platform=pc&upsig=7b626b942dab4437433e276e1dfd6c63&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&orderid=1,3&buvid=423719E5-C1F3-8E99-9949-C4F0FD92681D98687infoc&build=0&f=u_0_0&agrr=0&bw=107051&logo=40000000"],
  7.     "bandwidth": 855502,
  8.     "mimeType": "video/mp4",
  9.     "mime_type": "video/mp4",
  10.     "codecs": "hev1.1.6.L150.90",
  11.     "width": 1920,
  12.     "height": 1080,
  13.     "frameRate": "23.810",
  14.     "frame_rate": "23.810",
  15.     "sar": "1:1",
  16.     "startWithSap": 1,
  17.     "start_with_sap": 1,
  18.     "SegmentBase": {
  19.         "Initialization": "0-1570",
  20.         "indexRange": "1571-8935"
  21.     },
  22.     "segment_base": {
  23.         "initialization": "0-1570",
  24.         "index_range": "1571-8935"
  25.     },
  26.     "codecid": 12
  27. }
复制代码
我们看到有好几个url,实际上用第一个baseUrl即可。
现在我们拿到了视频真实地址,接下来该下载视频了,现在我们需要再回头分析视频下载请求。
先看请求头:

我们构造请求的时候可以把上面这些头都设置上,但是经过我的验证,实际上我们只需要设置下面这几个头即可:
Origin:就设置破站的域名即可
Referer:设置这个视频在浏览器地址栏中的地址即可
User-Agent:设置这个固定值即可
Range:上面截图设置的是bytes=0-1570,这个是咋回事?
观察一下上面的json,看到了吧,就设置为这个值就可以了。

是不是万事大吉了呢?根据以上思路,我构造了个请求试了下,果然还有问题,为啥?显然是Range:bytes=0-1570的问题。
不过,在这个请求的应答头里面,可以找到答案:

很显然,这个值就是视频的完整大小,所以,咱们设置为Range:bytes=0-3098152果然,下载下来了完整视频。
所以,我们的逻辑应该是,先设置Range:bytes=0-1570,请求一次,从这次请求的应答头中找到Content-Range,拿到视频的总大小3098152。再请求一次,设置Range:bytes=0-3098152,这次的应答,便是完整的视频文件了。
现在总该万事大吉了吧?打开视频检验一下。还是有点不对劲,只有人像,没有声音。
3、下载声音文件

再回看前面的完整json,视频文件信息是从data.dash.video路径下面找到的,我们看到还有一个data.dash.audio路径,显然,这是声音文件。
所以说破站是视频、音频分离的。
接下来我们还要把音频文件下载下来,下载过程跟上面视频文件是一致的,这里不再啰嗦了。
四、程序实现

代码基于SpringBoot,开发一个Web程序,部署到云服务器,供用户下载视频。
1、拿到完整json

根据前面的分析,我们首先请求视频在浏览器地址栏中的地址,拿到html。然后从html中拿到json,最后从json中拿到视频信息和音频信息,代码如下:
[code]logger.info("开始解析视频地址:{}",url);String html = restTemplate.getForObject(url,String.class);String regex = "(?




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4