📚博客主页:knighthood2001
公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下)
🎃知识星球:【认知up吧|成长|副业】介绍
❤️如遇文章付费,可先看看我公众号中是否发布免费文章❤️
🙏笔者水平有限,欢迎各位大佬指点,相互学习进步!

今天,我们来实现一下,B站视频的爬取。(本文仅供学习讨论)

首先要知道,B站视频清晰度和登录是息息相关的。

手动一下

你打开一个视频。
在这里插入图片描述

https://www.bilibili.com/video/BV1jt421c7yN/?vd_source=2ab95dfa6677af399778850be1824b83

学过爬虫的应该会知道,有些参数是可以不需要的。下面这个网址也能成功打开这个视频。

https://www.bilibili.com/video/BV1jt421c7yN/


接着,打开开发者工具(快捷键F12),点击网络(network)
在这里插入图片描述

然后将网页刷新一下。

在这里插入图片描述
上面这个文件看着比较特殊,打开看看。

可以发现,这个发送请求的url就是我们这个视频网址

在这里插入图片描述

同样,下面这个网址也能获得相应内容。

在这里插入图片描述

然后我们看看响应,发现里面有个video和audio,对应视频和音频。

此外,这个视频还有对应的高和宽
在这里插入图片描述
在这里插入图片描述

因此可以得出,我们获取到这几个网址(直接打开会提示403,因此需要假如一些参数进行爬取),就能把内容读取出来,然后保存到本地即可。

此外,也可以得出,b站视频和音频是分开的,你爬取后,需要进行合并处理。

题外话

经过以上分析,可以发现,视频网址中有我们需要的内容,但是我最开始,找了一圈,没找到。

后来发现,这内容藏在网页的head中。

包括网址,视频题目等等信息。

在这里插入图片描述
其中的视频、音频都藏在这里面。

在这里插入图片描述

此外,你可以发现,下面这两个文件,好像就是我上面返回内容中的网址。只是不知道哪个对应的是视频、哪个对应的是音频。
在这里插入图片描述
当然,你可以在返回信息中,工具m4s前面的几个数字进行查找,看其对应的是video视频还是audio音频

不过,据我观察,m4s前面有6位数字的,就是视频,前面是5位数字的,就是音频。


最笨的爬虫

有了以上的内容,其实你最基本的爬虫,就能写了。

首先就是,查看一下,网址和请求头需要的参数。
在这里插入图片描述
在这里插入图片描述
可以看到,User-AgentReferer是必须要的。此外,这个Referer的内容就是我们刚开始的网址。

Referer就是防盗链,用来告诉服务器你请求链接是从哪里跳转过来的,没有这个,就无法成功。(即使下载好后,打开文件,会显示无法播放)

在这里插入图片描述

因此,代码就能写了

# TODO 视频网址
url = 'https://www.bilibili.com/video/BV1jt421c7yN/'
headers = {
        # Referer 防盗链 告诉服务器你请求链接是从哪里跳转过来的
        # "Referer": "https://www.bilibili.com/video/BV1454y187Er/",
        "Referer": url,
        # User-Agent 用户代理, 表示浏览器/设备基本身份信息
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
    }
import requests
# TODO 通过F12查看视频的地址
video_url = 'https://xy183x214x144x8xy2409y8c50yda00y126yy8xy.mcdn.bilivideo.cn:4483/upgcxcode/83/23/1523062383/1523062383-1-100113.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1715968562&gen=playurlv2&os=mcdn&oi=1879749745&trid=00008c163333de3442dc929f4f62aff31adau&mid=691902317&platform=pc&upsig=a453aaa2553b8cd8f2fcca789fcd68d2&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&mcdnid=50002512&bvc=vod&nettype=0&orderid=0,3&buvid=2844B77E-F527-FB05-1DF5-9FDF834AE3E888277infoc&build=0&f=u_0_0&agrr=0&bw=25270&logo=A0020000'

video_response = requests.get(video_url, headers=headers)
with open('shiping.mp4', mode='wb') as v:
    v.write(video_response.content)
    
# TODO 通过F12查看音频的地址
audio_url = 'https://xy183x214x144x8xy2409y8c50yda00y126yy8xy.mcdn.bilivideo.cn:4483/upgcxcode/83/23/1523062383/1523062383-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1715968562&gen=playurlv2&os=mcdn&oi=1879749745&trid=00008c163333de3442dc929f4f62aff31adau&mid=691902317&platform=pc&upsig=a9e345e9808698097e942b690872ece1&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&mcdnid=50002512&bvc=vod&nettype=0&orderid=0,3&buvid=2844B77E-F527-FB05-1DF5-9FDF834AE3E888277infoc&build=0&f=u_0_0&agrr=0&bw=9931&logo=A0020000'
audio_response = requests.get(audio_url, headers=headers)
with open('yingping.mp3', mode='wb') as v:
    v.write(audio_response.content)

首先,你需要一个B站视频网址,然后你可以通过开发者工具,看到视频和音频的url,通过requests去获取二进制数据,然后保存到本地即可。

弊端:你需要复制视频、音频对应的url。

改进

以上代码,其实只是告诉你,有了视频、音频对应的url,如何去下载,因为直接打开对应的url,是提示403的。因此需要添加一些请求头(这里不需要Cookie)。

一般写爬虫,是只告诉一个视频网址,然后就进行爬取。接下来让我们实现这个。


由于我最开始说过,B站视频清晰度和登录有关,登录就涉及到Cookie,因此你需要复制你的Cookie。

在这里插入图片描述
然后构造一下请求头

headers = {
        # Referer 防盗链 告诉服务器你请求链接是从哪里跳转过来的
        # "Referer": "https://www.bilibili.com/video/BV1454y187Er/",
        "Referer": url,
        # User-Agent 用户代理, 表示浏览器/设备基本身份信息
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
        "Cookie": cookie
}

尽管https://www.bilibili.com/video/BV1jt421c7yN/网站中不需要Referer参数,但是这个参数在后面下载视频和音频的时候是需要的,并且现在加上,使用requests去访问,不会出现问题,因此我就加上这个Referer了,否则可能就得构造两个请求头,一个没有Referer,一个有Referer

然后你就可以去打印网页源代码,通过正则表达式获取视频标题。

# 发送请求
response = requests.get(url=url, headers=headers)
html = response.text
print(html)
# 解析数据: 提取视频标题
title = re.findall('title="(.*?)"', html)[0]
print(title)

此外,我们需要的视频和音频网址,都在window.__playinfo__=中。我们同样可以通过正则获取到这块内容。

这块内容,刚好还可以转换成字典格式,方便你通过键值对机制,获取到指定的url。

代码如下:

# 提取视频信息
info = re.findall('window.__playinfo__=(.*?)</script>', html)[0]
# info -> json字符串转成json字典
json_data = json.loads(info)
pprint(json_data)
# 提取视频链接
video_url = json_data['data']['dash']['video'][0]['baseUrl']
print(video_url)
# 提取音频链接
audio_url = json_data['data']['dash']['audio'][0]['baseUrl']
print(audio_url)

最后就是和最笨的爬虫一样,爬取视频音频内容,保存下来。


全部代码如下:

# 导入数据请求模块
import requests
# 导入正则表达式模块
import re
# 导入json模块
import json
# TODO 记得更改你要的url和你自己的cookie
url = 'https://www.bilibili.com/video/BV1jt421c7yN/'
cookie = "buvid3=2844B77E-F527-FB05-1DF5-9FDF834AE3E888277infoc; b_nut=1709986388; i-wanna-go-back=-1; b_ut=7; _uuid=6577D687-BED9-9AE2-106A10-551210627F5AC88087infoc; enable_web_push=DISABLE; buvid4=5ED5B3A0-A998-7D47-3815-9AD9A1B27A4989131-024030912-0Fw3r6dKwZLwPoWOl%2F8HuA%3D%3D; CURRENT_FNVAL=4048; rpdid=|(u|Jmkkuukk0J'u~u|ulR~)~; header_theme_version=CLOSE; fingerprint=c27c0b59dd10dcdc4c14701a58f49669; buvid_fp_plain=undefined; buvid_fp=c27c0b59dd10dcdc4c14701a58f49669; LIVE_BUVID=AUTO6217111182462626; FEED_LIVE_VERSION=V_WATCHLATER_PIP_WINDOW3; bp_video_offset_691902317=925084214145056785; DedeUserID=691902317; DedeUserID__ckMd5=ead312019baad7ed; CURRENT_QUALITY=80; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTYwNDM3MDgsImlhdCI6MTcxNTc4NDQ0OCwicGx0IjotMX0.Rdjc9F5oiEXSn_GylRWm3s2L-Pn8GYfyQS5IZt_Y3-8; bili_ticket_expires=1716043648; SESSDATA=3d6f944f%2C1731336513%2C491d2%2A51CjD5jp6zedAz4nQallTN_akUjFzg2LzJhdKMiJbI1nnw2bs5sp8Y09F7Jj4PofjUyfsSVlktMkF0aDRLN196dVNTeWh0czllbFZTWDlidWRpcnFnaENSNVVNbGNFMGR5bFBqYkcwalhuVklyUGJLVHJtYXo3TVpaTENqQ21rS0RPbldWTDUzRFp3IIEC; bili_jct=2975523315e5bccfa606ac286df61f36; home_feed_column=4; browser_resolution=1396-639; sid=6gr3y4l0; PVID=4; bp_t_offset_691902317=932475264446758937; b_lsid=5E9C415B_18F86EC150D"
headers = {
        # Referer 防盗链 告诉服务器你请求链接是从哪里跳转过来的
        # "Referer": "https://www.bilibili.com/video/BV1454y187Er/",
        "Referer": url,
        # User-Agent 用户代理, 表示浏览器/设备基本身份信息
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
        "Cookie": cookie
}
# 发送请求
response = requests.get(url=url, headers=headers)
html = response.text
print(html)
# 解析数据: 提取视频标题
title = re.findall('title="(.*?)"', html)[0]
print(title)
# 提取视频信息
info = re.findall('window.__playinfo__=(.*?)</script>', html)[0]
# info -> json字符串转成json字典
json_data = json.loads(info)
# 提取视频链接
video_url = json_data['data']['dash']['video'][0]['baseUrl']
print(video_url)
# 提取音频链接
audio_url = json_data['data']['dash']['audio'][0]['baseUrl']
print(audio_url)
video_content = requests.get(url=video_url, headers=headers).content
# 获取音频内容
audio_content = requests.get(url=audio_url, headers=headers).content
# 保存数据
with open('video\\' + title + '.mp4', mode='wb') as v:
    v.write(video_content)
with open('video\\' + title + '.mp3', mode='wb') as a:
    a.write(audio_content)

小结

希望我的讲解,大家能够看懂。

  • b站视频的爬取,我觉得最重要的就是去找到对应的网址,然后需要添加一些请求头,才能下载到本地且正常播放。
  • 本文没有将视频和音频合并起来。
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐