代码部分

获得弹幕
import re
import requests
import bs4
from bs4 import BeautifulSoup

#获取弹幕
def getDM(oid):
    r=requests.get('https://api.bilibili.com/x/v1/dm/list.so?oid='+oid)
    r.encoding=r.apparent_encoding
    return r.text
#截取有效弹幕部分
def cutDM(html):
    soup=BeautifulSoup(html,'html.parser')
    ls=soup.find_all('d')
    danmu=''
    for i in ls:
        content=''.join(i.string)
        danmu+=content
    #content=str(ls)
    #pattern=re.compile('<d.*?>(.*?)</d>')
    #danmu=pattern.findall(content)
    return danmu

def saveDM(danmu):
    f=open('danmu.txt','wt',encoding='utf-8')
    danmu=str(danmu)
    f.write(danmu)
def main():
    oid=input('请输入oid:')
    html=getDM(oid)
    danmu=cutDM(html)
    saveDM(danmu)


main()
制作词云
import wordcloud
from matplotlib.pyplot import imread
import jieba

txt=open('danmu.txt','r',encoding='UTF-8').read()
ls=jieba.lcut(txt)
content=' '.join(ls)
print(content)

mk=imread('C:/Users/ASUS/Pictures/sui1.jpg')
w=wordcloud.WordCloud(font_path='msyh.ttc',width=700,height=1000,background_color='white',mask=mk)

w.generate(content)
w.to_file('sui.png')

任务分析

首先爬取弹幕制作词云任务很明显的分为两个部分:数据爬取和数据分析。数据爬取时我们需要爬取B站的弹幕信息,但是由于弹幕信息并非直接显示在当前视频页面的html下,所以我们必须使用’检查‘来寻找存放弹幕信息的xml。爬取好了的弹幕我们需要进行处理,裁取出有效的部分,再进行词频的统计以及词云的制作。

弹幕爬取

在这个程序中,我们首先使用requests库进行网页爬取,但是由于这个例子比较简单,你也可以使用python自带的网络爬虫工具来完成。

由于B站弹幕页面header的编码格式并不是支持中文的utf-8,所以我们要更改页面编码格式,你可以把编码格式手动改为utf-8,也可以将编码格式改成页面实际编码格式。

然后我们可以使用r.text获得页面的所有信息。如果你还想再看一次的话,使用print()函数。

import requests
r=requests.get('https://api.bilibili.com/x/v1/dm/list.so?oid='+oid)
r.encoding=r.apparent_encoding
html=r.text
print(html)
弹幕裁取

在爬取好页面信息html后,我们使用BeautifulSoup库进行html页面的解析。将html解析成beautifulsoup类。

soup=BeautifulSoup(html,'html.parser')

在任务执行前对页面的分析或者刚刚我们用print()函数所看到的页面信息中,我们可以发现:弹幕内容被存放到了d标签中的字符串中。所以我们可以通过soup.find_all()来获得所有d标签。然后我们使用一个for循环获得单个标签,再通过tag.string 来获得b标签的字符串内容,即我们所需要的弹幕内容。

ls=soup.find_all('d')
danmu=''
for i in ls:
   content=''.join(i.string)
   danmu+=content

当然,你要是不嫌烦的话,可以按照网上许多教程所说的那样获得d标签的所有内容,然后再用正则表达式截取出弹幕内容。当然这样就比较麻烦,显然辜负了B站程序员们清楚的代码风格。但是这锻炼了你正则表达式的熟练度。

content=str(ls)
pattern=re.compile('<d.*?>(.*?)</d>')
danmu=pattern.findall(content)
词云制作

最后我们需要制作词云,由于B站弹幕绝大部分是中文,我们可以使用jieba库对弹幕内容进行分词。如果你想要更好的分词结果:比如支持日文和其他语言,你可能需要其他的工具支持。

import jieba

txt=open('danmu.txt','r',encoding='UTF-8').read()
ls=jieba.lcut(txt)
content=' '.join(ls)     #空格分隔词语,方便下一步词云的制作
print(content)            #检查

分词后我们就可以使用Wordcloud库进行词云制作了。如果你想要制作一个特别的词云,你可能需要mask的支持。mask可以理解为蒙版,可以使你的词云呈现特定的形状。你需要使用matplotlib.pyplot库来读取你的图片mask。最后将词云文件保存,任务完成。最后我们得到的结果如下:词云效果

import wordcloud
from matplotlib.pyplot import imread

mk=imread('C:/Users/ASUS/Pictures/sui1.jpg')
w=wordcloud.WordCloud(font_path='msyh.ttc',width=700,height=1000,background_color='white',mask=mk)

w.generate(content)
w.to_file('sui.png')

当然,这个任务还有很多可以优化的地方,比如我们可以直接通过BV号获得oid,而不用去寻找视频的oid;我们可以批量获得一个用户的所有视频的数据,制作数据量更大的词云;我们还可以支持多语言的分词,设置词表来达到更好的分词效果。有空我会继续更新。

优化1:直接通过BV号获得oid(4.4完成)

如果直接使用requests库的get去爬取页面的话,我们无法看到视频的oid,所以为了模拟人真实的行为来获得我们所需要的数据,我们需要使用selenium库来模仿一个浏览器进行操作。

from selenium import webdriver
driver=webdriver.Firefox()
driver.get('https://www.bilibili.com/video/'+bv)

上面我们模拟了火狐浏览器对url进行访问,这时候我们就可以做到所见即所得了。

对视频url进行爬取之后我们需要对我们获得的无比复杂的视频源页面的oid进行分析,具体过程如下:

soup=BeautifulSoup(html,'html.parser')
content=soup.find(string=re.compile(r'.bilivideo.com/upgcxcode'))
a=''
a+=content
b=a.split('base_url')
c=''
c+=b[0]
d=c.split('upgcxcode')
e=''
e+=d[1]
content=e.split('/',4)
oid=content[3]

这里的思路就是用split不断进行切割,最后得到视频的oid。

接下来的步骤就和之前一样了。

优化2:批量获得一个用户的所有视频的数据(4.4完成)

想了想很简单,其实优化1和2对之前的我的关键难点就是无法模拟人的操作,在掌握了selenium之后这些难题就迎刃而解了。

这个优化可以这样实现:

1.获取用户的uid并访问其空间

2.获取空间中的视频bv号

3.沿用优化1的方法

优化3:更好的分词效果