手把手教你爬取B站弹幕!
阅读原文时间:2023年07月08日阅读:1

效果

输入要爬取的视频的BV号即可爬取该视频的弹幕。

过程

基本的思路很简单,还是老步骤:

1、构造爬取的url

2、解析返回的数据

3、使用json或Xpath或正则表达式提取数据

4、保存数据

第一步

刚开始还是从网页版中寻找url地址,结果请求很多,找了半天也没有找到

第二步

于是我们可以访问一下手机版的页面,而根据常识,弹幕这种东西一般是通过ajax来请求的,所以我们过滤一下,只看异步请求。

此时请求就变得少了很多,但是依然没有找到我们需要的弹幕数据,此时才发现我们并没有点击播放视频。

第三步

弹幕是在视频播放的过程中播放的,理所当然只有当我们播放视频并且打开弹幕后才会请求弹幕的数据,我们点击播放。

点击播放后我们可以发现请求变多了,再次寻找我们发现 168881748.xml 请求的地址便是弹幕数据了。

第四步

到这里我们就想到了,这种地址是怎么请求的呢?不同的视频请求的地址肯定是不一样的,应该是js生成的吧!现在我们来搜索一下该文件名``168881748`

很显然这是构造出来的地址,我们点进去看一下

不出所料是js构成的请求地址,我们可以发现这便是页面的数据,我们进一步去验证一下,刷新页面,查看一下网页的数据。

果然在该页面的文档中我们找到了

现在思路就很清晰了

1、通过视频url获取弹幕文件url

2、爬取弹幕文件url

3、提取数据

代码实现

# coding=utf-8
import requests
from lxml import etree
import re
class BiliSpider:
    def __init__(self,BV):
        # 构造要爬取的视频url地址
        self.BVurl = "https://m.bilibili.com/video/"+BV
        self.headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Mobile Safari/537.36"}

    # 弹幕都是在一个url请求中,该url请求在视频url的js脚本中构造
    def getXml_url(self):
        # 获取该视频网页的内容
        response = requests.get(self.BVurl, headers = self.headers)
        html_str = response.content.decode()
        # 使用正则找出该弹幕地址
        # 格式为:https://comment.bilibili.com/168087953.xml
        # 我们分隔出的是地址中的弹幕文件名,即 168087953
        getWord_url = re.findall(" '//comment.bilibili.com/'+ (.*) +'.xml',", html_str)
        getWord_url = getWord_url[0].replace("+","").replace(" ","")
        # 组装成要请求的xml地址
        xml_url = "https://comment.bilibili.com/{}.xml".format(getWord_url)
        return xml_url

    # Xpath不能解析指明编码格式的字符串,所以此处我们不解码,还是二进制文本
    def parse_url(self,url):
        response = requests.get(url,headers = self.headers)
        return response.content

    # 弹幕包含在xml中的<d></d>中,取出即可
    def get_word_list(self,str):
        html = etree.HTML(str)
        word_list = html.xpath("//d/text()")
        return word_list

    def run(self):
        # 1.根据BV号获取弹幕的地址
        start_url = self.getXml_url()
        # 2.请求并解析数据
        xml_str = self.parse_url(start_url)
        word_list = self.get_word_list(xml_str)
        # 3.打印
        for word in word_list:
            print(word)

if __name__ == '__main__':
    BVName = input("请输入要爬取的视频的BV号:")
    spider = BiliSpider(BVName)
    spider.run()

这里只打印了弹幕,并没有保存,可以根据自己的需求进行更改!