Python爬虫:爬取B站视频(最新、能用且讲解详细)【01】

📚博客主页: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站视频的爬取,我觉得最重要的就是去找到对应的网址,然后需要添加一些请求头,才能下载到本地且正常播放。
  • 本文没有将视频和音频合并起来。
Python 爬虫爬取 B 站视频通常涉及到网页数据抓取、解析以及处理等步骤。下面简要介绍如何使用 Python 和相应的库完成这一任务: ### 选择合适的工具 对于网页爬取Python 提供了多种强大的库,如 `requests` 用于发起 HTTP 请求,`BeautifulSoup` 或 `lxml` 用于解析 HTML 页面内容。 ### 获取视频链接 首先,你需要确定你要爬取视频链接。B 站的视频链接一般由几个部分组成: 1. **频道ID**(Channel ID) 2. **视频ID**(Video ID) 例如,链接可能是 `/video/avxxxxxx` 的形式,其中 `'xxxxxx'` 即为视频 ID。 ### 使用 Python 进行请求和解析 #### 发起 GET 请求 使用 `requests.get()` 函数获取页面的内容。这一步主要是为了获取到包含视频信息的相关 HTML 内容。 ```python import requests from bs4 import BeautifulSoup def get_video_html(video_id): url = f'https://www.bilibili.com/video/{video_id}' response = requests.get(url) if response.status_code == 200: return response.text else: print('Failed to fetch the video page') return None ``` #### 解析页面内容 使用 `BeautifulSoup` 对获取的HTML文本进行解析,查找包含视频播放地址的标签或属性。 ```python def parse_video_url(html_text): soup = BeautifulSoup(html_text, 'html.parser') # 假设视频链接在script标签内隐藏,需要找到并提取出来 script_tag = soup.find('script', id='_playInfoScript') if script_tag is not None: play_info = eval(script_tag.string) # 将字符串转换为字典 video_url = play_info['data']['dash']['video']['baseUrl'] return video_url else: print('Video URL not found') return None ``` ### 下载视频 有了视频的实际链接,就可以下载视频内容了。这里可以使用 `requests` 的 `stream=True` 参数进行大文件下载,并通过迭代逐块读取和保存。 ```python import os def download_video(video_url, output_file): response = requests.get(video_url, stream=True) total_size_in_bytes = int(response.headers.get('content-length', 0)) progress_bar_length = 50 with open(output_file, "wb") as file: for data in response.iter_content(chunk_size=8192): file.write(data) done = int(50 * len(file.read()) / total_size_in_bytes) percent_done = (len(file.read()) / total_size_in_bytes) * 100 print(f'\rDownloading... [{("█" * done).ljust(progress_bar_length)}] {percent_done:.2f}%', end='') print() if __name__ == "__main__": video_id = 'xxxxxx' html_text = get_video_html(video_id) if html_text: video_url = parse_video_url(html_text) if video_url: filename = f'av{video_id}.mp4' download_video(video_url, filename) print(f'Successfully downloaded {filename}') else: print('Could not find a valid video URL.') else: print('Failed to fetch video content.') ``` ### 法律及伦理考虑 请注意,在进行网络爬虫活动时,务必遵守网站的使用条款和法律法规。特别是从网站上抓取数据前,应检查其robots.txt 文件,并确认是否允许爬虫访问相关数据。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

knighthood2001

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

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

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

打赏作者

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

抵扣说明:

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

余额充值