想下载B站视频却不知如何下手?一文教你爬B站!

本文介绍了如何使用Python爬取哔哩哔哩视频并进行音视频合成。从最初的moviepy库合成方法,由于效率低下,转向使用ffmpeg工具,大大提高了合成速度。通过分析网页源码,实现了直接输入视频URL获取音视频文件并进行合成,同时处理了文件命名和大小显示。最后,通过优化代码,实现了动态获取视频名称,避免了重名问题,并展示了完整代码示例。
摘要由CSDN通过智能技术生成

初级版本

首先,我们先试着实现爬取一个视频保存到本地,随便在哔哩哔哩网站找一个视频,如我找的一个链接:https://www.bilibili.com/video/BV1Sz4y1Z7g9?from=search&seid=7693898795687978846

右键检查,点击network抓包,点击播放:
在这里插入图片描述
我们会看到很多的数据包,经过尝试分析我们点开带30280,会看到response响应部分就是很多我们看不懂的编码二进制数据,实际上30280数据包就是是一个纯音频文件(没有画面),而30080数据包是一个纯视频文件(没有声音),那么现在思路就有了,我们想办法把视频和音频文件都爬取下来,然后再想办法合成不就行了?
在这里插入图片描述
效率较低的方式,便是利用第三方库moviepy合成,准备工作需要安装moviepy,安装命令:pip install moviepy -i http://pypi.douban.com/simple/
代码实现如下:

import requests
from moviepy.editor import *
if __name__ == '__main__':
    # 1.确认url
    url_30080 = 'https://cn-jxnc-cmcc-bcache-06.bilivideo.com/upgcxcode/91/22/237582291/237582291_nb2-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1605200882&gen=playurl&os=bcache&oi=3719332261&trid=aa176f00ecf448b294d69b0cf06670f8u&platform=pc&upsig=efa32de99996e526857889b34eca24a1&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&cdnid=4205&mid=440047762&orderid=0,3&agrr=0&logo=80000000'
    url_30280 = 'https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/91/22/237582291/237582291_nb2-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1605200882&gen=playurl&os=cosbv&oi=3719332261&trid=aa176f00ecf448b294d69b0cf06670f8u&platform=pc&upsig=2ae2924502e57ee4ab092da37af359ba&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=440047762&orderid=0,3&agrr=0&logo=80000000'
    # 设置用户代理
    headers_ = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
        'Referer':'https://www.bilibili.com/video/BV1CT4y1w7Ed?from=search&seid=6176037271681914381'
    }

    # 2.发送请求得到响应
    response_30080 = requests.get(url_30080,headers=headers_)
    response_30280 = requests.get(url_30280,headers=headers_)

    data_30080 = response_30080.content
    data_30280 = response_30280.content

    # 保存
    with open('斗罗大陆_30080.mp4','wb') as f:
        f.write(data_30080)

    with open('斗罗大陆_30280.mp3','wb') as f:
        f.write(data_30280)

    """
    在拥有了一个纯视频文件,跟一个纯音频文件的情况下......
    利用第三方库moviepy合成():速度很慢  
    """

    # 选择一个已经拥有的纯视频文件
    video_obj = VideoFileClip('斗罗大陆_30080.mp4')

    # 选一个对应已拥有的纯音频文件
    audio_obj = AudioFileClip('斗罗大陆_30280.mp3')

    # 往视频对象里面添加音频
    movie_ = video_obj.set_audio(audio_obj)

    # 保存
    movie_.write_videofile('斗罗大陆_.mp4')

过程(效率极低,贼慢(大概5-10分钟),提前打招呼。。。建议趁这段时间听听音乐看看小视频打发一下时间~):
在这里插入图片描述
废了老大时间,终于跑完了,控制台结果是这样的:
在这里插入图片描述
在当前路径下,打开合成后的mp4文件,播放效果如下:
在这里插入图片描述

有声音有画面,证明我们已经成功实现了一个视频的爬取,但是使用moviepy合成音视频文件是不是太慢了,这么费时间怎么让人受的了?有没有更高效的方法?当然有,下面介绍一款强大的视频合成利器。

改进版本

准备工作:安装配置ffmpeg
那什么是ffmpeg呢?百度上给出了这样的定义:FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。我们只需要知道ffmpeg是一款非常好用处理音视频的工具包就行了,如果想深入了解大家可以自行在网上找一些学习资料,我们今天的目的只有一个:合成音视频!
ffmpeg功能强大,但我们首先得学会对其进安装(windows下安装),很简单的,下载解压后配置好环境变量就OK了。
安装参考链接:Windows安装配置ffmpeg

安装好之后我们就可以用代码控制ffmpeg合成音视频文件了,代码编写如下:

import requests
import os
if __name__ == '__main__':
    # 1.确认url
    url_30080 = 'https://cn-jxnc-cmcc-bcache-06.bilivideo.com/upgcxcode/91/22/237582291/237582291_nb2-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1605200882&gen=playurl&os=bcache&oi=3719332261&trid=aa176f00ecf448b294d69b0cf06670f8u&platform=pc&upsig=efa32de99996e526857889b34eca24a1&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&cdnid=4205&mid=440047762&orderid=0,3&agrr=0&logo=80000000'
    url_30280 = 'https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/91/22/237582291/237582291_nb2-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1605200882&gen=playurl&os=cosbv&oi=3719332261&trid=aa176f00ecf448b294d69b0cf06670f8u&platform=pc&upsig=2ae2924502e57ee4ab092da37af359ba&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=440047762&orderid=0,3&agrr=0&logo=80000000'
    # 设置用户代理
    headers_ = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
        'Referer':'https://www.bilibili.com/video/BV1CT4y1w7Ed?from=search&seid=6176037271681914381'
    }

    # 2.发送请求得到响应
    response_30080 = requests.get(url_30080,headers=headers_)
    response_30280 = requests.get(url_30280,headers=headers_)

    data_30080 = response_30080.content
    data_30280 = response_30280.content

    # 保存
    with open('斗罗大陆30080.mp4','wb') as f:
        f.write(data_30080)
        print('纯视频文件下载完毕......')
    with open('斗罗大陆30280.mp3','wb') as f:
        f.write(data_30280)
        print('纯音频文件下载完毕......')
    # 利用第三方工具ffmpeg 合成视频, 需要执行终端命令
    os.system('ffmpeg -i 斗罗大陆30280.mp3 -i 斗罗大陆30080.mp4 -c copy 斗罗大陆.mp4 -loglevel quiet')
    # 后面的-loglevel quiet加不加无所谓,不加控制台会出现红色的log日志但不影响代码功能。
    print('视频合成成功......')

可以看到瞬间就合成成功了,打开看看效果,完全不差:
在这里插入图片描述
我们再比较一下内存大小,同样的音视频文件使用moviepy合成的mp4文件大小为120404KB

在这里插入图片描述
而使用ffnpeg合成的mp4文件大小为74273KB,接近音视频大小加起来的总和,合成后的画质音质也是无损的,所以无论是从时间效率还是从空间损耗方便来讲,可以说ffmpeg完虐moviepy!
在这里插入图片描述
仔细想想我们只想要合成后的视频文件,分开的音视频文件没啥用,白白的占用了内存,想到这里代码还可以再优化一下,在合成后删除音视频文件即可,那我们只需要在以上代码最后加上两行删除指令的代码即可:

 os.system('del 音频名称.mp3')
 os.system('del 视频名称.mp4')

这两行代码调用的是操作系统的指令删除的,也可以用remove删除,即os.remove(‘音频名称.mp3’),这个无所谓,只要能达到删除目的就行。

升级版本

到目前为止,我们已经能爬取指定的视频了,但是爬一个视频我们就要解析30080,30280的数据包获取相关url对我们来说是非常不便的。我们想要达到的效果是输入目标视频的url直接就能下载视频。
开始尝试解决,

  1. 复制纯视频url进行全局搜索,右上角三个点,菜单栏选择search
    在这里插入图片描述

  2. 把https删掉s 进行搜索,找到了该文件(存有我们纯视频url)

在这里插入图片描述
3. 点开那条搜索数据,点击pretty-print 格式化输出
在这里插入图片描述
4.点击文件区域,ctrl + f 继续搜索
在这里插入图片描述

发现纯视频文件的url 和纯音频文件的url都在同一个文件当中, 如果我们能够获取到这个文件的response,那么就能够提取出url进行请求,保存,合成…

该文件实际为url地址栏的url请求对应的response,那解析出视频音频文件url就简单了,我们可以使用用正则提取,其实仔细分析可以发现我们还可以指定清晰度版本,就是那个id,80,64,32等等就是对应的版本,我们这里不再赘述,直接爬取最高画质,要搞就搞最好的,编写代码如下:

import re
import os

if __name__ == '__main__':
    url  = input('请输入要下载的视频url:')

    headers ={
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
        "cookie": "_uuid=425019D2-6E06-C2BA-320C-989D73E268D379095infoc; buvid3=A7BFF32C-6475-484D-AD68-D6B1633AD9CE53937infoc; LIVE_BUVID=AUTO3815878009223382; rpdid=|(J~R~kuRY)l0J'ul)~)||mkJ; DedeUserID=440047762; DedeUserID__ckMd5=ad5ddee3544a770f; SESSDATA=d392227d%2C1604025506%2C3577b*51; bili_jct=883303557689d9fa49b97229f5837edd; CURRENT_QUALITY=64; PVID=1; CURRENT_FNVAL=80; blackside_state=1; bsource=search_baidu; sid=kjvz5hpk"
    }

    res = requests.get(url,headers =headers).text
    html = etree.HTML(res)
    str_url_list = html.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]
    audio_str = re.findall(r'"audio":\[{"id":30280,"baseUrl":"(.*?)"', str_url_list)[0]
    vidio_str = re.findall(r'"video":\[{"id":80,"baseUrl":"(.*?)"',str_url_list)[0]

    # print("音频:",audio_str)
    # print("视频:", vidio_str)
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
        "referer":url
    }
    audio_response = requests.get( audio_str,headers=headers).content
    vidio_response = requests.get(vidio_str, headers=headers).content

    with open('音频.mp3','wb') as f:
        f.write(audio_response)

    with open('视频.mp4','wb')as f:
        f.write(vidio_response)

    os.system('ffmpeg -i 音频.mp3 -i 视频.mp4 -c copy 合成后的视频.mp4 -loglevel quiet')
    time.sleep(2)
    os.system('del 音频.mp3')
    os.system('del 视频.mp4')

随便找一个视频复制url尝试一下,我用的这个url(斗罗大陆小姐姐):

https://www.bilibili.com/video/BV19C4y147GK?from=search&seid=7693898795687978846

下载成功:在这里插入图片描述
打开合成好的视频,效果:
在这里插入图片描述

最终加强版本

优化:

  • 问题1:我们下载下来的视频名称是否能够改成网页视频原名?

可行性分析: 网页里面的视频名称,已知网页为html数据,名称也可以使用xpath调试拿到。

  • 问题2: 这个视频可以利用//span[@class=“tit”]/text() 取到视频名称
  • 在这里插入图片描述

其他视频有的,xpath语法并不通用,改xpath取视频名称通用 //title/text()
在这里插入图片描述

需要切割后面多余的部分,可以通过xpath语法提取到名称,再进行一个切片,正则提取就可以了

  • 问题3: 视频的名称中,如果包含 空格 / & 都会影响到视频的合成
    解决办法, 去掉名称中的 空格 / & 等特殊字符

  • 问题4:title_ = 斗罗大陆
    纯视频文件: 斗罗大陆!.mp4
    纯音频文件: 斗罗大陆!.mp3
    合成的文件: 斗罗大陆.mp4
    为了避免因为重名造成的问题,可以添加一个字符,改变一下视频名称,避免重名。

  • 问题5:如何在控制台想显示文件的大小.
    –1,发送请求的时候,参数添加stream=True
    –2.获取大小

参考代码如下:


import requests
import os
from lxml import etree
import re

if __name__ == '__main__':
    # 输入网页的url
    url_ = input('请输入一个网址:')

    # 设置用户代理,cookie
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'Cookie': "INTVER=1; _uuid=09E58359-9210-BAEE-1A60-4EE46A2B82C655513infoc; sid=5ytmp0pi; LIVE_BUVID=AUTO6515760552512495; stardustvideo=1; laboratory=1-1; rpdid=|(umuum~uku|0J'ul~Y|llkl); buvid3=684E90B9-B796-4512-AE61-CED715ED0D2B53931infoc; stardustpgcv=0606; finger=158939783; DedeUserID=246639322; DedeUserID__ckMd5=0de51babcf36bfe1; SESSDATA=0453e7c3%2C1613286482%2C848b7*81; bili_jct=05a501d5099630a42cb271cebdbc3470; blackside_state=1; CURRENT_FNVAL=80; CURRENT_QUALITY=80; bsource=search_baidu; PVID=4"
    }

    # 发送请求,得到响应对象
    response_ = requests.get(url_, headers=headers_)

    str_data = response_.text  # 视频主页的html代码,类型是字符串

    # 使用xpath解析html代码,,得到想要的url
    html_obj = etree.HTML(str_data)  # 转换格式类型

    # 获取视频的名称
    res_ = html_obj.xpath('//title/text()')[0]
    # 视频名称的获取
    title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]
    # 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了
    title_ = title_.replace('/', '')
    title_ = title_.replace(' ', '')
    title_ = title_.replace('&', '')

    # 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串
    url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]

    # 纯视频的url
    video_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 纯音频的url
    audio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]

    # 设置跳转字段的headers
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
        'Referer': url_
    }

    # 获取纯视频的数据
    response_video = requests.get(video_url, headers=headers_, stream=True)
    bytes_video = response_video.content
    # 获取纯音频的数据
    response_audio = requests.get(audio_url, headers=headers_, stream=True)
    bytes_audio = response_audio.content

    # 获取文件大小, 单位为KB
    video_size = int(int(response_video.headers['content-length']) / 1024)
    audio_size = int(int(response_audio.headers['content-length']) / 1024)

    # 保存纯视频的文件
    title_1 = title_ + '!'  # 名称进行修改,避免重名
    with open(f'{title_1}.mp4', 'wb') as f:
        f.write(bytes_video)
        print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')

    with open(f'{title_1}.mp3', 'wb') as f:
        f.write(bytes_audio)
        print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')

        # 利用第三方工具ffmpeg 合成视频, 需要执行终端命令
    os.system(f'ffmpeg -i {title_1}.mp3 -i {title_1}.mp4 -c copy {title_}.mp4 -loglevel quiet')

    # 显示合成文件的大小
    res_ = int(os.stat(f'{title_}.mp4').st_size / 1024)
    print(f'{title_}视频合成成功...,大小为{res_}KB, {int(res_/1024)}MB......')

    # 移除纯视频文件,
    os.remove(f'{title_1}.mp4')
    # 移除纯音频文件,
    os.remove(f'{title_1}.mp3')

再随便找一个url 测试,https://www.bilibili.com/video/BV1kp4y1v7QM?from=search&seid=7693898795687978846
成功!
在这里插入图片描述
播放效果:
在这里插入图片描述
感谢各位小伙伴的阅读,如有任何问题可在评论区留言或者csdn app发私信给我,看到了一定知无不言言无不尽。。。

最后送出一些福利,感兴趣的自取:C++及Python人工智能500G+学习资源

  • 23
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
LVS(Linux Virtual Server)是一种基于 Linux 系统的负载均衡集群技术,它主要用于将网络流量分发到多个服务器上,以提高系统的可靠性、可扩展性和性能。 LVS 集群一般包括四个组件:调度器(LVS 调度器)、前端服务器(负载均衡器)、后端服务器(真实服务器)和存储服务器(用于共享数据)。首先,调度器接收来自客户端的请求,然后根据配置的调度算法(如轮询、加权轮询、最小连接数等)将请求分发到多个前端服务器。前端服务器接收到请求后,通过相应的负载均衡算法将请求转发到后端的真实服务器上进行处理。在整个过程中,存储服务器用于存放共享的数据,以确保所有的真实服务器都能获取到相同的数据,并提供一致的服务。 LVS 集群的优点是能够提高网站的稳定性和可靠性,当某一台服务器出现故障时,调度器会自动将请求分发到其他可用的服务器上,从而保证服务的连续性。同时,LVS 集群还能够通过增加前端服务器和后端服务器的数量来提高系统的性能和吞吐量,以满足不断增长的用户需求。 在实际应用中,LVS 集群需要合理配置,包括选择合适的调度算法、调整每台服务器的权重、选择适当的硬件设备等。此外,还需要及时监控集群的运行状态,及时发现和解决故障,以确保整个系统的正常运行。 总的来说,LVS 负载均衡集群是一种强大而高效的集群技术,能够帮助企业提高系统的可靠性和性能,是现代互联网应用中不可或缺的重要组成部分。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰履踏青云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值