Python爬虫:爬取Bilibili视频(.m4s)

您所在的位置:网站首页 合并m4s Python爬虫:爬取Bilibili视频(.m4s)

Python爬虫:爬取Bilibili视频(.m4s)

2024-07-12 23:02:44| 来源: 网络整理| 查看: 265

本文仅作为学习笔记参考使用: 哔哩哔哩视频抓取 b站视频的抓取还是比较困难的,相对于其他的网站的视频获取相对难一些,也是因为我的好奇不怕死心理,打算拿b站视频好好分析分析,具体抓取流程如下:

初始分析页面如下: 在这里插入图片描述 这个页面有点养眼,就从这个开始。本页面的请求以及响应信息较为容易抓取分析,主要就是获取分页标记以及视频跳转到指定播放界面的url地址(如下图所示)在这里插入图片描述 我用的办法是把响应中的页面框架信息下载下来,然后与原始合并之后的Element页面对比,从而找出url,这一步不难找,就不多说了,直接上代码(en…大体代码就这样,我也懒得一点点分离了):

html_str01 = self.get_request(self.index_url, self.index_headers).content.decode("utf-8") seconed_url_list = set( re.findall(r'''href="//(www\.bilibili\.com/video/.*?\?from=search)"''', html_str01, re.S))

接下来,找到了初始url,我们就可以去分析原始视频抓取了: 下面就是来到这个页面,进行分析: 在这里插入图片描述 我们通过抓包,是获取不到完整的视频请求地址的,而是获取到一大批 .m4s格式文件的请求。初始猜测.m4s格式文件就是我们需要的视频文件,但是从数目上来看,是视频片段,可是,并不是所有的.m4s格式的请求都是一样的,大体分成(如下图所示的)这样几个请求,划掉的哪个肯定不是,因为响应为null,所以就剩下3类请求(30080 / 30216 / 30232)。 在这里插入图片描述 三种请求,那么哪一种是我需要的呢?继续分析,找了很多资料,得出结论,返回请求数据多的为视频格式,返回数据量少的是音频文件(如下图所示) 30080需要的请求的总数据大小在这里插入图片描述 30216需要的请求的总数据大小 在这里插入图片描述 30232需要的请求的总数据大小 在这里插入图片描述 相比较而言,30080 > 30232 > 30216 的数据请求量 现在可以肯定的是 30080 这个数据请求的是视频文件,那么30232和30216这两个请求的文件,哪一个才是音频文件呢? 不慌,接着往下分析。 这里有个问题,30080文件有那么多个片段,我不能全部都下载下来然后再合成⑧,虽然这确实可行,但是比较复杂。还有更简单的方式获得整个视频文件,这个就需要在requests请求头里 把 Range(如下图所示) 这个参数改成 bytes 0-XXXXXXXX 这种形式,而这里的 XXXXXXXX 就是在上文中我们分析url类型的数据请求总数量,并且据我分析,这个值只能大于或者等于数据请求总量,而不能小于。所以这里有两种的方法获取完整的.m4s格式的方法,一种就是,把请求头的Range的值写的贼大,另一种就是,先请求 0-5 这样比较短的数据,进行返回头部试探,获取到响应头部以后再取到准确的数据量的值,然后再发送请求获取.m4s全部数据的请求,这样就获取到完整的.m4s格式的文件了在这里插入图片描述 在这个分析的基础之上,对刚刚拿不准的 30232 和 30216格式的url请求进行对比,分别测试取得两种请求获取的数据,进行对比。如图所示:在这里插入图片描述 我们下载下来两种请求到的数据,并全部保存为.mp3文件格式,通过本次测试得到,两个文件均为视频的音频文件,两者无差别。故此,我们请求稍微小一点的 30216。 这样,视频音频文件的获取就可以完成了,只不过,这里是分离开下载的,如果需要合成的话,这里说一下我尝试的两种方法: 【1】使用ffmpeg模块完成视音频合成 【2】使用 格式工厂 本程序中我没有使用ffmpeg来合成,原因由两个。一是因为实在是太慢了,并且转化过程中我笔记本cpu占用率升到了不可思议的 99%,二是因为格式工厂实在是太好用了,合成速度极快。故此,我选择了手动的格式工厂来合成视音频。

至此,整个分析流程结束,剩下的就是把整个程序写出来,这里就不说具体每个模块怎么写了,直接奉上代码截图及运行截图。

运行截图如下: 在这里插入图片描述 代码进行中部分保存结果展示:在这里插入图片描述 视频播放展示:✔插一句,是高清,没错的 在这里插入图片描述 故此,本程序介绍结束: 部分码如下:在这里插入图片描述 源码某部分

def run(self): # print("第一次请求开始。。。。。") html_str01 = self.get_request(self.index_url, self.index_headers).content.decode("utf-8") # file_name = re.findall(r'''(.*?)''', html_str01, re.S)[0] + ".mp4" seconed_url_list = set( re.findall(r'''href="//(www\.bilibili\.com/video/.*?\?from=search)"''', html_str01, re.S)) # print(seconed_url_list) for seconed_url in seconed_url_list: html_str02 = self.get_request("http://" + seconed_url, self.index_headers).content.decode("utf-8") try: m4s_30080 = re.findall(r'''"baseUrl":"(.*?)"''', html_str02, re.S)[0] except Exception as e: print(e) continue if self.audio_condition == 'Y': mp3_30216 = re.findall(r'''"baseUrl":"(.*?)"''', html_str02, re.S)[-2] # print(m4s_30080) Referer_key = seconed_url # 试探请求头大小 Range_key = 'bytes=0-5' self.seconed_headers['Referer'] = 'https://' + Referer_key self.seconed_headers['Range'] = Range_key # 试探,取得total的值 html_bytes = self.get_request(m4s_30080, headers=self.seconed_headers).headers['Content-Range'] if self.audio_condition == 'Y': audio_bytes = self.get_request(mp3_30216, headers=self.seconed_headers).headers['Content-Range'] # print(html_bytes) total = re.findall(r"/(.*)", html_bytes, re.S)[0] if self.audio_condition == 'Y': audio_total = re.findall(r"/(.*)", audio_bytes, re.S)[0] # print("total: " + str(total)) self.seconed_headers['Range'] = total # print(total) stream = True chunk_size = 1024 # 每次块大小为1024 content_size = int(total) if self.audio_condition == 'Y': content_size_audio = int(audio_total) print("文件大小:" + str(round(float((content_size + content_size_audio) / chunk_size / 1024), 4)) + "[MB]") else: print("文件大小:" + str(round(float(content_size / chunk_size / 1024), 4)) + "[MB]") start = time.time() m4s_bytes = self.get_request(m4s_30080, headers=self.seconed_headers, stream=stream) self.write_data(str(self.num) + ".mp4", m4s_bytes, chunk_size, content_size) if self.audio_condition == 'Y': print("\n") self.seconed_headers['Range'] = audio_total mp3_bytes = self.get_request(mp3_30216, headers=self.seconed_headers, stream=stream) self.write_data(str(self.num) + ".mp3", mp3_bytes, chunk_size, content_size_audio) end = time.time() print("总耗时:" + str(end - start) + "秒") self.num = self.num + 1


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭