整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

python爬取B站网页弹幕内容,并将爬取内容以五角星的形式显示出来

路:

  • 向哔哩哔哩网站发送请求
  • 请求成功后,解析爬取的弹幕内容保存到一个文件中
  • 读取文件并分析弹幕内容中词组或文字出现的频率
  • 将这些词组或文字组成五角星图形
  • 组成五角星图形后,以图片的形式输出

使用到的类库,如果没有,需要下载,下载命令:

pip install requests
pip install bs4
pip install pandas
pip install lxml # 在解析xml文件时,需要使用
pip install jieba
pip install wordcloud
pip install imageio
pip install matplotlib

实现:

import requests
from bs4 import BeautifulSoup
import pandas as pd
import re
import jieba
from wordcloud import WordCloud
from imageio import imread
import matplotlib.pyplot as plt
​
'''
python学习交流群:821460695更多学习资料可以加群获取
'''
# 网页地址,该地址只针对哔哩哔哩弹幕网有效,获取方式查看
url = "http://comment.bilibili.com/124001121.xml"
​
# 网站访问的用户代理,建议携带,不携带可能无法访问
header = {
 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
}
​
# 向对方服务器发送请求,返回访问状态,
# 返回状态如果是以[2]开头,表示访问成功,[4]开头表示网页不存在,[5]开头网站内部错误
# 访问状态无法直接读取,需通过属性[text]获取
response = requests.get(url,header)
​
# 获取网页的编码规则,建议通过该方式获取,而不是直接赋值,可能存在设置不对的情况,可能不是中文网页
# response.encoding = "utf-8"
response.encoding = response.apparent_encoding
# print(response.text)
​
# 获取网页文本内容
data = response.text
'''
--将获取到的弹幕内容处理后存放在txt文件中,并读取出来
--网页获取的弹幕内容是带html标签的,需要将标签和非汉字的内容清除
'''
# 解析文本xml,处理不规范标记并生成剖析树
soup = BeautifulSoup(data,'lxml') 
# print(soup)
# 获取所有<d>标签中的内容,此时是带标签的文本内容
d_list = soup.find_all('d')
​
# 去掉<d>标签,将文本内容存在在列表dlst
dlst = []
for d in d_list:
 danmu = {}
 danmu['弹幕'] = d.text # 循环获取所有<d>标签中内容
 dlst.append(danmu)
​
df = pd.DataFrame(dlst) # 将列表dlst中的内容存放在数据集中,类似于Excel表格
# print(df)
​
# 创建并打开一个文件
f = open('cl.txt','w',encoding='utf-8')
# 进行文本过滤
for i in df['弹幕'].values: # 遍历数据集中的所有的弹幕内容
 pat = re.compile(r'[一-龥+]') # 定义过滤规则,只保留中文汉字,该正则表达式几乎包含了所有汉字龥(yu,第四声)
 filter_data = re.findall(pattern=pat,string=i) # 执行过滤操作
 f.write(''.join(filter_data)) # 将过滤后的弹幕内容写入创建的[cl.txt]文件中
f.close()
​
'''
--读取弹幕内容所在的文件[cl.txt]
'''
f1 = open('cl.txt','r',encoding='utf-8')
data = f1.read()
​
'''
--将弹幕内容分割成词组,并组合成五角星的图案
'''
result = " ".join(jieba.lcut(data))
​
f1.close()
color_mask = imread("五角星.jpg") # 设置数据组合的图形,最好使用空心的图片
wc = WordCloud(
 font_path="C:\Windows\Fonts\simsun.ttc", # 数据显示的字体
 width=1000,
 height=800,
 background_color='white', # 词云的背景色
 mask=color_mask # 词云组成的图形,默认为二维
)
​
wc.generate(result) # 将弹幕内容生成词云
wc.to_file('clanned.png') # 词云输出文件
​
'''
--显示弹幕内容组成的图片
'''
plt.imshow(wc)
plt.show()

知识点:

  • request 向对方服务器发送请求
  • BeautifulSoup 解析爬取的弹幕内容
  • pandas 分析弹幕数据
  • jieba 中文分词器,或称为中文词组切片器
  • wordcloud 加载弹幕文本,并输出文件(这里使用图片的方式输出)
  • matplotlib.pyplot 将整理后的弹幕文本以图形的方式输出(这里是以五角星的图片为例)
  • imread 读取图片

问题:

  • 爬取的弹幕内容被保存在了文件后,后又重新读取,是否可以不存放在文件中,直接使用列表或者其他对象存储,然后再读取?保存在文件和直接读取的优缺点是什么?
  • 弹幕内容中除了汉字,实际上还包含了大量的字母,表情符号,这些内容可以通过什么正则表达式进行筛选,能否同时跟汉字一起筛选出来?
  • 在导包的时候,使用[from scipy.misc import imread]报错,用[from imageio import imread]代替即可。为什么使用scipy.misc中的imread报错?

.前言

在上一篇文章【[以『赘婿』为实战案例,手把手教会你用python爬取『爱奇艺』视频弹幕]】,教会了大家如何爬取爱奇艺弹幕

本文将在上文的基础上继续完善,爬取更多的弹幕数据进行可视化分析!

同样还是以『赘婿』为例,下面将爬取全部弹幕数据,约7w+条数据!!!

2.采集数据

1.寻找url




上文介绍到,每一集都需要通过查看数据把获取弹幕的url

因此,我们需要去获取这些的弹幕url!!!


tv_name_list =[
'',
'/54/00/7973227714515400',
'/57/00/4779805474835700',
'/37/00/1016845483273700',
'/77/00/8679935826337700',
'/46/00/7197533339804600',
'/48/00/8042213977424800',
'/98/00/2262609044749800',
'/94/00/1699488619659400',
'/47/00/1805374511564700',
'/46/00/1933721047194600',
'/08/00/7232026471250800',
'/59/00/8982352350925900',
'/43/00/4702797553454300',
'/38/00/2151107991923800',
'/93/00/8357465155589300',
'/29/00/2071693573022900',
'/71/00/4646645944127100',
'/39/00/1182091647913900',
'/31/00/7711721648193100',
'/58/00/2099769377685800',
'/83/00/3042314248738300',
'/21/00/2889100571832100',
'/98/00/3374410909698000',
'/37/00/4335405595243700',
'/32/00/5215381530163200',
'/11/00/2379725258541100',
'/48/00/4872856713204800',
'/08/00/1488519001760800',
]

以上就是弹幕url参数!!!

2.请求数据


def get_data():
    for k in range(1,len(tv_name_list)):#29个 1-28
        url_id = tv_name_list[k]
        for x in range(1,11):
            # x是从1到11,11怎么来的,这一集总共46分钟,爱奇艺每5分钟会加载新的弹幕,46除以5向上取整
            try:
                url = 'https://cmts.iqiyi.com/bullet'+str(url_id)+'_300_' + str(x) + '.z'
                xml = download_xml(url)
                # 把编码好的文件分别写入个xml文件中(类似于txt文件),方便后边取数据
                with open('./lyc/zx'+str(k) +'-'+ str(x) + '.xml', 'a+', encoding='utf-8') as f:
                    f.write(xml)
            except:
                pass




这样就可以将含有的弹幕信息的xml文件下载到本地!

3.合并数据到excel


import openpyxl
outwb = openpyxl.Workbook()  # 打开一个将写的文件
outws = outwb.create_sheet(index=0)  # 在将写的文件创建sheet

"""
import xlwt
# # 创建一个workbook 设置编码
workbook = xlwt.Workbook(encoding = 'utf-8')
# # 创建一个worksheet
worksheet = workbook.add_sheet('sheet1')
#
# # 写入excel
# # 参数对应 行, 列, 值
# worksheet.write(0,0, label='index')
# worksheet.write(0,1, label='tvname')
# worksheet.write(0,2, label='uid')
# worksheet.write(0,3, label='content')
# worksheet.write(0,4, label='likeCount')
"""
outws.cell(row = 1 , column = 1 , value = "index")
outws.cell(row = 1 , column = 2 , value = "tvname")
outws.cell(row = 1 , column = 3 , value = "uid")
outws.cell(row = 1 , column = 4 ,  value = "content")
outws.cell(row = 1 , column = 5 , value = "likeCount")

避坑:
之前我们使用xlwt来保存数据到excel,但是最多写到65535行,这次我们采用openpyxl来写入到excel!!!


def xml_parse(file_name,tv__name):
    global  count
    DOMTree = xml.dom.minidom.parse(file_name)
    collection = DOMTree.documentElement
    # 在集合中获取所有entry数据
    entrys = collection.getElementsByTagName("entry")

    for entry in entrys:
        uid = entry.getElementsByTagName('uid')[0]
        content = entry.getElementsByTagName('content')[0]
        likeCount = entry.getElementsByTagName('likeCount')[0]
        #print(uid.childNodes[0].data)
        #print(content.childNodes[0].data)
        #print(likeCount.childNodes[0].data)
        # 写入excel
        # 参数对应 行, 列, 值
        outws.cell(row=count, column=1, value=str(count))
        outws.cell(row=count, column=2, value=str("第"+str(tv__name)+"集"))
        outws.cell(row=count, column=3, value=str(uid.childNodes[0].data))
        outws.cell(row=count, column=4, value=str(content.childNodes[0].data))
        outws.cell(row=count, column=5, value=str(likeCount.childNodes[0].data))
        count=count+1

这样就可以将xml里的数据保存到excel


def combine_data():
    for k in range(1,29):
        for x in range(1,11):
            try:
                xml_parse("./lyc/zx"+str(k) +"-"+ str(x) + ".xml",k)
                print(str(k) + "-" + str(x))
            except:
                pass
    # 保存
    #workbook.save('弹幕数据集-李运辰.xls')
    outwb.save("弹幕数据集.xls")  # 保存结果


这样7w+条弹幕数据可以完全写入到excel中,命名为 弹幕数据集.xls

3.数据可视化

1.浏览数据


# 导包
import pandas as pd

#读入数据
df_all = pd.read_csv("弹幕数据集.csv",encoding="gbk")
df = df_all.copy()

# 重置索引
df = df.reset_index(drop=True)
print(df.head())




说明:1.index序号、2.tvname集数、3.uid用户id、4.content评论、5.likeCount评论点赞数

2.累计发送弹幕数的用户


#累计发送弹幕数的用户
def an1():
    danmu_counts = df.groupby('uid')['content'].count().sort_values(ascending=False).reset_index()
    danmu_counts.columns = ['用户id', '累计发送弹幕数']
    name = danmu_counts['用户id']
    name = (name[0:10]).tolist()
    dict_values = danmu_counts['累计发送弹幕数']
    dict_values = (dict_values[0:10]).tolist()

    # 链式调用
    c = (
        Bar(
            init_opts=opts.InitOpts(  # 初始配置项
                theme=ThemeType.MACARONS,
                animation_opts=opts.AnimationOpts(
                    animation_delay=1000, animation_easing="cubicOut"  # 初始动画延迟和缓动效果
                ))
        )
            .add_xaxis(xaxis_data=name)  # x轴
            .add_yaxis(series_name="累计发送弹幕数的用户", yaxis_data=dict_values)  # y轴
            .set_global_opts(
            title_opts=opts.TitleOpts(title='', subtitle='',  # 标题配置和调整位置
                                      title_textstyle_opts=opts.TextStyleOpts(
                                          font_family='SimHei', font_size=25, font_weight='bold', color='red',
                                      ), pos_left="90%", pos_top="10",
                                      ),
            xaxis_opts=opts.AxisOpts(name='用户id', axislabel_opts=opts.LabelOpts(rotate=45)),
            # 设置x名称和Label rotate解决标签名字过长使用
            yaxis_opts=opts.AxisOpts(name='累计发送弹幕数'),

        )
            .render("累计发送弹幕数的用户.html")
    )


3.查看某个用户评论情况


#查看某个用户评论情况
def an2():
    df_top1 = df[df['uid'] == 2127950839].sort_values(by="likeCount", ascending=False).reset_index()
    print(df_top1.head(20))


4.用户(2127950839)每一集的评论数


#查看用户(2127950839)每一集的评论数
def an3():
    df_top1 = df[df['uid'] == 2127950839].sort_values(by="likeCount", ascending=False).reset_index()
    data_top1 = df_top1.groupby('tvname')['content'].count()
    print(data_top1)
    name = data_top1.index.tolist()
    dict_values = data_top1.values.tolist()
    # 链式调用
    c = (
        Bar(
            init_opts=opts.InitOpts(  # 初始配置项
                theme=ThemeType.MACARONS,
                animation_opts=opts.AnimationOpts(
                    animation_delay=1000, animation_easing="cubicOut"  # 初始动画延迟和缓动效果
                ))
        )
            .add_xaxis(xaxis_data=name)  # x轴
            .add_yaxis(series_name="查看用户(2127950839)每一集的评论数", yaxis_data=dict_values)  # y轴
            .set_global_opts(
            title_opts=opts.TitleOpts(title='', subtitle='',  # 标题配置和调整位置
                                      title_textstyle_opts=opts.TextStyleOpts(
                                          font_family='SimHei', font_size=25, font_weight='bold', color='red',
                                      ), pos_left="90%", pos_top="10",
                                      ),
            xaxis_opts=opts.AxisOpts(name='集数', axislabel_opts=opts.LabelOpts(rotate=45)),
            # 设置x名称和Label rotate解决标签名字过长使用
            yaxis_opts=opts.AxisOpts(name='评论数'),

        )
            .render("查看用户(2127950839)每一集的评论数.html")
    )


5.剧集评论点赞数最多的评论内容


#剧集评论点赞数最多的评论内容
def an4():
    df_like = df[df.groupby(['tvname'])['likeCount'].rank(method="first", ascending=False) == 1].reset_index()[['tvname', 'content', 'likeCount']]
    df_like.columns = ['集', '弹幕内容', '点赞数']
    print(df_like)


6.评论内容词云


#评论内容词云
def an5():
    contents = (df_all['content']).tolist()

    text = "".join(contents)
    with open("stopword.txt", "r", encoding='UTF-8') as f:
        stopword = f.readlines()
    for i in stopword:
        print(i)
        i = str(i).replace("\r\n", "").replace("\r", "").replace("\n", "")
        text = text.replace(i, "")
    word_list = jieba.cut(text)
    result = " ".join(word_list)  # 分词用 隔开
    # 制作中文云词
    icon_name = 'fas fa-play'
    gen_stylecloud(text=result, icon_name=icon_name, font_path='simsun.ttc',
                   output_name="评论内容词云.png")  # 必须加中文字体,否则格式错误


4.总结

1.爬取了7w+『赘婿』弹幕,保存到excel(数据分享给大家)!
2.通过pandas读取excel并进行相关统计计算!
3.以可视化方式
分析好的数据进行可视化展示!

京网络举报微信公众号

为切实保障广大网民合法权益,维护良好网络生态,中央网信办启动了为期1个月的“清朗·网络戾气整治”专项行动。按照专项行动工作部署安排,北京市网络舆情和举报中心启动“清朗·网络戾气整治”专项举报工作,及时受理社会公众举报。

一、举报受理范围

专项举报行动重点围绕社交、短视频、直播等重点平台类型,重点受理的违法和不良信息范围是:

1.“网络厕所”“开盒挂人”行为。创建专门的BOT账号、贴吧、话题、群组等,通过匿名投稿、隔空喊话等方式,接收并发布针对特定群体或个人的嘲讽讥笑、恶意评价、诅咒谩骂信息。以揭露、批评等名义恶意“开盒”“挂人”,公开他人姓名、身份证号、手机号码、家庭住址、工作单位、个人照片、社交账号等个人隐私信息,煽动网民攻击谩骂。

2.借社会热点事件恶意诋毁、造谣攻击。对突发案事件相关当事人进行造谣污蔑,或者剪辑加工与事实严重不符的图片、视频,诱导网民对当事人进行攻击质疑。利用热点事件当事人形象,制作发布表情包,使用AI软件合成低俗色情、血腥恐怖等虚假图片或视频,进行造谣攻击、恶搞诋毁。

3.污名化特定群体、煽动地域对立。将个别恶性社会事件、负面人物与性别、职业、地域等特征相关联,对特定群体污名化、打负面标签,发布性别对立、阶层对立、地域歧视言论,进行泛化攻击,激化社会矛盾。

4.斗狠PK等低俗不良直播行为。网络主播利用逞勇斗狠、PK饮酒、谩骂吐脏等行为,涨粉引流。在他人直播过程中,利用弹幕、连麦等功能进行人身攻击,甚至怂恿鼓动自杀自残等极端行为。编造打架约架等暴力冲突剧本,吸引网民围观,扰乱公共秩序。

5.有组织地恶意辱骂举报他人。以“帮忙做事”“解忧解气”等名义,提供有偿代骂服务,对特定账号进行留言辱骂、私信攻击。组织粉丝群体使用平台“举报”“反黑”等功能,恶意批量举报他人。发布娱乐、体育、电竞等领域拉踩引战、恶意炒作言论,诱导粉丝互撕谩骂、刷量控评。

6.编造网络黑话、恶意造梗。通过拼音、谐音、指代词等方式,恶意编造低俗烂梗、不良流行语,污染网络风气。使用污言秽语、粗口脏话,故意挑起矛盾、制造对立冲突。

7.煽动网上极端情绪。编造耸人听闻的帖文标题,发布无中生有、毫无底线的“泄愤帖”。恶意夸大师生矛盾,渲染家长“压迫”“压榨”孩子,挑起关系对立,对未成年人形成不良导向。刻意渲染消极负面、焦虑怨愤情绪,散布仇视对立言论。

二、举报受理方式

1.举报咨询电话:010-67196565

2.举报网址:www.bjjubao.org.cn

3.北京属地网站举报方式:www.bjjubao.org.cn/2023-04/23/content_42964.html

欢迎广大网民积极提供相关举报线索,共同维护清朗网络空间。