手把手带你B站少量弹幕爬取并生成词云

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。

手把手带你B站少量弹幕爬取并生成词云

最近准备爬虫大作业,突然想到爬取B站弹幕,于是马上行动。

一、先看看要用到的库

import requests
from bs4 import BeautifulSoup
import re
import pandas as pd
import time
import numpy as np
from PIL import Image
import jieba
import wordcloud
复制代码

其中requests和bs4以及re是爬虫的主力军,而numpy、Image、jieba、wordcloud就是生成词云要用到的东西。pandas是便于格式化来输出文件是。

二、定义一些要用到的数据结构和请求头

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36 FS"}
​
video_time=[]
abstime=[]
userid=[]
comment_content=[]
复制代码

这里我们主要使用列表存储数据,请求头后面有两个函数需要用到,我们就将它放在外面吧。

三、寻找API

经过查询资料,我们知道类似于api.bilibili.com/x/v1/dm/lis…这种链接可以获取到部分弹幕信息。然后我们来访问看一看。

image.png

是个xml文件,我们发现只需要获取这个oid参数就能获取某个视频的弹幕信息。

然后寻找视频对应的oid信息。

接着我们发现了api.bilibili.com/x/player/pa…。这个链接就能获取视频链接的oid,就是这个cid

image-20211101211900906

接着是获取bvid,这个就是视频链接中包含的信息。

就是这个链接www.bilibili.com/video/BV1aJ…

四、获取cid

def get_cid(url):
    data = requests.get(url=url,headers=headers)
    data = data.json()
    cid = data['data'][0]['cid']
    return cid
复制代码

我们发现获取cid的页面是个json文件,然后我们可以将直接取json文件中的cid的值。

五、获取弹幕信息

def get_info(url):
    html = requests.get(url=url, headers=headers)
    html.encoding = html.apparent_encoding
    
    soup = BeautifulSoup(html.text,'lxml')
    
    data_number=re.findall('d p="(.*?)">',html.text)
    data_text=re.findall('">(.*?)</d>',html.text)
    
    comment_content.extend(data_text)
    for each_numbers in data_number:
        
        each_numbers=each_numbers.split(',')
        
        video_time.append(each_numbers[0])           
        abstime.append(time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(int(each_numbers[4]))))      
        userid.append(each_numbers[6])
        
    result={'用户id':userid,'评论时间':abstime,'视频位置(s)':video_time,'弹幕内容':comment_content}
    results=pd.DataFrame(result)
    final= results.drop_duplicates()
    final.info()
    final.to_excel('B站弹幕.xls')
复制代码

这里我们还是获取那个xml文件,然后利用正则表达式获取xml中各个列的值,我们保存用户编号,评论时间,弹幕的视频位置,弹幕内容。然后保存到xls文件中。

六、分词

def getWord(text):
    cut_txt = jieba.cut(text)
    result = " ".join(cut_txt)
    print(result[:30])
    return result
复制代码

这里介绍简单的利用jieba分词。然后将分词结果拼接成一个字符串。

七、生成词云

def setWordCloud():
    pic = np.array(Image.open("./cat.jpg"))
    stopwords = set(wordcloud.STOPWORDS)
    stopwords.add("好")
    font = r".\妙笔生花.ttf"
    wc = wordcloud.WordCloud(
            font_path=font,
            background_color="white", 
            max_words=1000, 
            mask=pic,
            stopwords=stopwords,
            max_font_size=30,
            random_state=45
        )
    return wc
​
def getWordCloud(wc,result):
    wc.generate(result)
    wc.to_file("./wordcloud.jpg")
复制代码

通过分词结果生成词云,然后导出图片。

八、主函数

def main():
    url = "https://www.bilibili.com/video/BV1aJ411C7tb/?spm_id_from=autoNext"
    cid_url = "https://api.bilibili.com/x/player/pagelist?bvid="+str(url[31:43]) +"&jsonp=jsonp"
    cid = get_cid(cid_url)
    oid_url = 'https://api.bilibili.com/x/v1/dm/list.so?oid='+str(cid)
    get_info(oid_url)
    
    content = " ".join(comment_content)
    word = getWord(content)
    wc = setWordCloud()
    getWordCloud(wc, word)
    
复制代码

主函数比较简单,就是调用函数。在爬取弹幕方面,我们将网址中的信息进行提取和填充。在生成词云方面,我们先将弹幕信息拼接然后取分词,再来生成词云。