Python大作业——弹幕数据分析(获取url cid 弹幕 画出词云)

2023-10-10 20:20

本文主要是介绍Python大作业——弹幕数据分析(获取url cid 弹幕 画出词云),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 首先要知道我们要做什么,要是茫无目的那就说明都做不了,我们这次的数据分析

步骤:

① 获取视频url

② 获取视频cid

③ 获取视频弹幕

第一步:获取视频url

解析我在弹幕里直接写了,可以自己看一看,我就不在博客里写了,不好排版

Get_Url代码部分

from bs4 import BeautifulSoup
from selenium import webdriverurl = 'https://space.bilibili.com/517327498/channel/seriesdetail?sid=60119'
print("------------开始罗翔说评论地址------------")  # 2021-11-6 edg VS DK# chrome驱动,需要放在Python安装的目录下
driver = webdriver.Chrome(r"C:\Users\12430\AppData\Local\Programs\Python\Python39\chromedriver.exe")driver.get(url)
data = driver.page_source  # 获取到页面信息
# print(data)
soup = BeautifulSoup(data, 'lxml')  # 我们可以利用他解析HTML代码,并且在解析HTML代码的时候,如果
# HTML代码不规范或者不完整,lxml解析器会自动修复或补全代码,从而提高效率
# print(soup)  # 不信你查看一下count = 1
res = []all = soup.find_all('li', attrs={'class': 'small-item fakeDanmu-item'})  # 找到这个专辑里的视频,只要是
# B站的专辑都在这个class里
print("all: ", end="")
print(all)
# print(all)  # 不信你看一下for li in all:if count <= 15:  # 罗翔的这个专辑视频就15个,所以爬15次a = li.find('a', attrs={'class': 'cover cover-normal'})print("这是a: ", end="")print(a)res.append('https:' + a.get("href"))  # href的格式是//www.bilibili.com/video/BV1k44y1g7Dp这样count += 1else:break
print(res)
with open('Urls/链接.txt', 'w') as f:  # 将结果放入这个文件里for link in res:f.write(link + '\n')
print("已将全部链接放入到链接.txt文件中")

第二步:获取视频cid

① 首先我们要定位到这个cid到第放在了什么鬼地方,发现在下面这个位置

 在script中,我们发现cid好出现在了这个window.__playinfo__中,所以我们要想办法获取他它,这边有一个办法就是startswith()这个方法

② 知道cid位置以后就想这么获取它就行了 

首先用startswith()获取链接,不知道为什么罗翔老师的视频不是//cn开头而是//upos(图一),

通过正则表达式的方法获取到cid的部分(图二)。

 然后通过一系列的处理获取前9个数字,至此获取cid成功

Get_Cid 代码部分

from bs4 import BeautifulSoup
from selenium import webdriver
import re
import timecids = []
Urls = []cid_start = 15
# sets_end = len(open('Urls/Link.txt', 'r').readlines()) + sets_start - 1anime_name = "《罗翔读评论》"with open('Urls/Link.txt', 'r') as f:for line in f.readlines():Urls.append(line.strip())print("开始爬取动漫" + anime_name + "所有视频的Cid")# chrome驱动,需要放在Python安装的目录下
driver = webdriver.Chrome(r"C:\Users\12430\AppData\Local\Programs\Python\Python39\chromedriver.exe")
link = ''  # 需要先定义,后面查找url的时候可能会应为找不到url而导致link未定义
cid = ''
for url in Urls:driver.get(url)data = driver.page_sourcesoup = BeautifulSoup(data, 'lxml')all = soup.find_all('script')for a in all:if str(a).startswith("<script>window.__playinfo__"):  # 必须这样否则找不到res = a# print(res)links = re.split(r':', str(res))# print("-----------------------")# print(links)for url in links:# 这个链接前面是域名,中国的都是以cn开头,但是现在好像不是了if url.startswith("//"):  # 不知道为什么有些视频不是//cn开头的,所以用//来实现print(url)print("-----------------------")link = urlbreakcid = re.findall(".*/(.*)-1-.*", link)# 获取到视频的cid,存进数组然后一起存进Cid.txt文件中cid = cid[0]# 处理特殊情况下,长度不符合cid,去除尾部部分# 需要根据Cid进行特殊处理if len(cid) > 9:length = len(cid)a = length - 9cid = cid[:-a]# print(cid)cids.append(cid)# 每抓完一个网页休眠5秒time.sleep(5)print(anime_name + "第" + str(cid_start) + "集Cid爬取完毕")cid_start -= 1print(cid)with open('Urls/Cid.txt', 'w') as f:for id in cids:f.write(id + '\n')print("已将全部视频的Cid放入到Cid.txt文件中")

第三步:获取视频的弹幕

① 首先我们需要一个headers 获取 用户代理 和 Cookie,这个自己用F12找找就行,

然后开始寻找视频的时间,首先我们发现罗翔老师读评论的第一期和最后一期好像是2020/7/14和

2022/4/29来着,那么我们就设置2020/7/13到2022/4/30来寻找视频日期

②  开始获取弹幕数据,这边就不用图片了,代码太长了

 第一步,首先要知道<d></d>这个标签里的这么多数字是什么

第一个参数 17.57900 记作DM_time,是弹幕在视频中出现的时间,以秒数为单位。

第二个参数 1 记作DM_mode,是弹幕的模式1…3 滚动弹幕 4底端弹幕 5顶端弹幕 6.逆向弹幕 7精准定位 8高级弹幕

第三个参数 25 记作DM_font,是字号, 12非常小,16特小,18小,25中,36大,45很大,64特别大

第四个参数 16777215 记作DM_color,是字体的颜色以HTML颜色的十进制为准

第五个参数 1653783652  记作DM_realTime,是发送弹幕的时间戳

第六个参数 0 记作DM_pool,是弹幕池 0普通池 1字幕池 2特殊池(高级弹幕)

第七个参数 def8eb39记作DM_userID,是发送者的ID,用于“屏蔽此弹幕的发送者”功能

第八个参数 1062823650710860544 记作DM_id,是弹幕在弹幕数据库中rowID,也就是这条弹幕是历史总弹幕的第几条

第九个参数 11 这个玩意好像没什么用?

弹幕本体 记作DM_text

 Get_BulletChat部分

import re
import jieba
from bs4 import BeautifulSoup
import time
import pandas as pd
import requests
import datetimeheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/102.0.5005.63 Safari/537.36","Connection": "keep-alive",# 这个cookie的获取方法在文档中已说明"Cookie": "buvid3=F2278A54-EB90-05CA-6AC4-25606AB151A009225infoc; CURRENT_FNVAL=4048; ""b_lsid=10C7E85F4_1812E57B9D8; _uuid=1CCF3FED-9CA9-4996-69104-410F55A4243FE10121infoc; ""buvid4=AD4080D0-B5E7-8064-1B21-3F1AFE743B2510754-022060418-h0Kdr2RwgtcfH98SEPYQ1Q%3D%3D; ""buvid_fp=16eaee4e45e32b194417c0880035c419; CURRENT_BLACKGAP=0; blackside_state=0; sid=7hhsqlnl; ""rpdid=|(J|)Yllu|k~0J'uYlRJJmmuY; ""b_timer=%7B%22ffp%22%3A%7B%22333.788.fp.risk_F2278A54%22%3A%221812E57C17E%22%2C%22333.999.fp"".risk_F2278A54%22%3A%221812E5BBF35%22%7D%7D "
}
sets = 15  # 最新一期的数字
anime_name = "罗翔读评论"
dates = []  # 日期数组,用于填充url
# 遍历日期  包括begin和end的日期  生成类似2020-04-29的格式的日期
begin = datetime.date(2020, 7, 13)
end = datetime.date(2022, 4, 30)
# 需要一天一天找,所以比较慢
d = begin
delta = datetime.timedelta(days=1)  # 一天一天找
while d <= end:dates.append(str(d.strftime("%Y-%m-%d")))d += delta
# print(dates)
#Cids = []  # Cid数组,用于填充url
with open('Urls/Cid.txt', 'r') as f:for line in f.readlines():Cids.append(line.strip())
print(Cids)  # 15--1for cid in Cids:print("正在爬取第" + str(sets) + "期的" + anime_name + "弹幕...")# 每次都要重置这些数据dm_data = []  # 弹幕数据dm_text = []  # 弹幕本体# 弹幕的八个参数和弹幕本体DM_time = []  # 弹幕时间DM_mode = []  # 弹幕模式DM_font = []  # 弹幕类型DM_color = []  # 弹幕颜色DM_realTime = []  # 弹幕时间戳DM_pool = []  # 弹幕池DM_userID = []  # 弹幕发送者IDDM_id = []  # 弹幕是弹幕数据库中的第几条DM_text = []print("正在爬取第" + str(sets) + "期的弹幕...")for date in dates:url = 'https://api.bilibili.com/x/v1/dm/list.so?oid=' + cidresponse = requests.get(url=url, headers=headers)  # 返回文本信息response.encoding = 'utf-8'soup = BeautifulSoup(response.text, 'lxml')  # 建立soup对象all = soup.find_all("d")  # d是弹幕标签# print(all)for d in all:# 弹幕数据dm_data.append(str(d.get("p")).split(","))  # p是标签# 弹幕本体dm_text.append(d.get_text())print("第" + str(sets) + "集" + " " + str(date) + "数据爬取完毕!")# 分别把数据存进这几个数组for i in dm_data:DM_time.append(i[0])DM_mode.append(i[1])DM_font.append(i[2])DM_color.append(i[3])DM_realTime.append(i[4])DM_pool.append(i[5])DM_userID.append(i[6])DM_id.append(i[7])for i in dm_text:DM_text.append(i)#  利用pandas进行csv文件的写入dt = {"DM_time": DM_time, "DM_mode": DM_mode, "DM_font": DM_font, "DM_color": DM_color,"DM_realTime": DM_realTime, "DM_pool": DM_pool, "DM_userID": DM_userID, "DM_id": DM_id, "DM_text": DM_text}d = pd.DataFrame(dt)d.to_csv('./Danmu/Danmu-' + str(sets) + '.csv', encoding='utf-8')  # 存储弹幕信息print("已将弹幕放入到Danmu-" + str(sets) + ".csv文件中")sets -= 1# 每抓完一个网页休眠7秒print("缓冲中...")time.sleep(5)print("已将罗翔读评论的第①期到第①⑤期的弹幕爬取完毕")

第四步,开始作图

主要功能:

import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
import os
from wordcloud import WordCloud
import jiebaanime_name = "罗翔读评论"
file_dir = "./Danmu/"
# 获取文件名
files = [files for root, dirs, files in os.walk(file_dir)]
print(files)# 去重
def duplicate(files):for file in files:print(file)data_df = pd.DataFrame()df = pd.read_csv(file_dir + file, encoding="utf-8-sig", index_col=0, engine='python')df = pd.concat([data_df, df])# 开始去重data = df.drop_duplicates(subset=['DM_id'], keep='first')data.to_csv(file_dir + file, encoding='utf-8-sig', index=True, index_label="")print("去重完毕")# 每一期弹幕总数的变化折线图
def danmuSumPlot(files):print("弹幕总数变化图绘制中...")list1 = ['1', '2', '3', '4','5', '6', '7', '8','9', '10', '11', '12','13', '14', '15']data_sum = []for file in files:data = pd.read_csv(file_dir + file, encoding="utf-8-sig", index_col=0)data_sum.append(len(data))matplotlib.rcParams["font.family"] = "SimHei"plt.plot(list1, data_sum, "m", ':')plt.ylabel("弹幕数量")plt.xlabel("《罗翔读评论》期数")plt.title("每一期弹幕总数的变化图")plt.savefig('./Analysis/弹幕分析图片/弹幕总数变化图', dpi=800)plt.show()print("绘制完毕")# 发弹幕总数TOP10的用户柱状图
def danmuUserTopBarh(files):print("弹幕TOP20用户图绘制中...")datas = []for file in files:datas.append(pd.read_csv(file_dir + file, encoding="utf-8", index_col=0))# 先合并全部csv文件,再进行统计data = pd.concat(datas)data = data.groupby('DM_userID').size().reset_index(name="count")data = data.sort_values("count", ascending=False)label = []  # y轴的值width = []  # 给出具体每个直方图的数值i = 0for item in data.values:if i < 20:label.append(item[0])width.append(item[1])i += 1else:breakmatplotlib.rcParams["font.family"] = "SimHei"y = [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]  # 给出在y轴上的位置plt.barh(y=y, width=width, tick_label=label)  # 绘制水平直方图plt.ylabel("用户ID")plt.xlabel("弹幕数")plt.title("发弹幕总数TOP20的用户柱状图")plt.subplots_adjust(left=0.22)  # 控制图片左边的间隔  避免显示不全plt.savefig('./Analysis/弹幕分析图片/TOP20柱状图', dpi=600)print("绘制完毕")# 每期弹幕密度变化图
def danmuDensityChange(files):print("弹幕密度变化图绘制中...")sets = 1for file in files:data = pd.read_csv(file_dir + file, encoding="utf-8-sig", index_col=0)data = data.sort_values("DM_time")# 先对弹幕发送时间进行取整data['DM_time'] = [int(item) for item in data.DM_time]data = data.groupby('DM_time').size().reset_index(name="counted")list2 = [item for item in data.DM_time]data_sum = [item for item in data.counted]matplotlib.rcParams["font.family"] = "SimHei"plt.plot(list2, data_sum, "c")plt.ylabel("弹幕数量")plt.xlabel("视频时间轴/(秒)")plt.title(str(sets) + "期弹幕密度变化图")plt.savefig("./Analysis/弹幕密度变化/" + str(sets) + '期弹幕密度变化图', dpi=600)sets += 1print("绘制完毕")# 每期的弹幕词云,词云已经用jieba库进行去词了
def danmuWordCloud(files):print("弹幕词云绘制中...")sets = 1for file in files:data = pd.read_csv(file_dir + file, encoding="utf-8-sig", index_col=0)# 先把全部弹幕信息写成一个字符串,再调用方法words = ''for item in data.DM_text:words += itemwords = " ".join(jieba.cut(words))# 这个scale参数是画布大小参数,也就是调整分辨率的,10代表是原来的10倍大小,越高分辨率越高wd = WordCloud(font_path='simhei.ttf',max_words=80,background_color='white',min_font_size=5,width=1920,height=1080,scale=10).generate(words)plt.imshow(wd)plt.axis("off")wd.to_file("./Analysis/词云/第" + str(sets) + "期词云.jpg")sets += 1print("绘制完毕")# 每期的弹幕词云(jieba去词以后-带图片背景)
def danmuWordCloud_Img(files):print("弹幕词云绘制中...")# df = pd.DataFrame()# jieba.load_userdict("./Tools/" + anime_name + "词汇.txt")sets = 1sets_s = 1for file in files:data = pd.read_csv(file_dir + file, encoding="utf-8", index_col=0)# 先把全部弹幕信息写成一个字符串,再调用方法words = ''for item in data.DM_text:words += str(item)# print(words)with open('./自定义文件/stopwords.txt', 'r+', encoding='utf-8') as fp:stopwords = fp.read().split('\n')  # 将停用词词典的每一行停用词作为列表中的一个元素word_list = []  # 用于存储过滤停用词后的分词结果'seg_list = jieba.cut(words)for seg in seg_list:if seg not in stopwords:word_list.append(seg)words = " ".join(word_list)mask = plt.imread('./Analysis/maskImages/' + anime_name + '.jpg')  # 读取图片作为词云图轮廓# if sets == 15:#     sets = 1# 这个scale参数是画布大小参数,也就是调整分辨率的,10代表是原来的10倍大小,越高分辨率越高wd = WordCloud(font_path='simhei.ttf',max_words=800,background_color='white',min_font_size=1,# width=1920,# height=1080,mask=mask,scale=5).generate(words)plt.imshow(wd)plt.axis("off")wd.to_file("./Analysis/带形状词云/" + anime_name + "第" + str(sets_s) + "集词云_Image.jpg")# sets += 1sets_s += 1print("绘制完毕")# 弹幕颜色直方图
def DM_color(files):plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falsefor file in files:data_df = pd.DataFrame()data = pd.read_csv(file_dir + file)  # 读取数据文件data = pd.concat([data_df, data])  # 拼接数据data_color = data['DM_color'].value_counts()  # 统计用户发送的弹幕使用同一种颜色的数量data_color = data_color.head(7)  # 选出前七种颜色favorite_color = []  # 弹幕颜色的十六进制颜色码# 将爬取到的十进制颜色码转换为十六进制颜色码for a_color in data_color.index:temp = hex(a_color)temp = '#' + temp[2:].upper()while len(temp) < 7:temp = temp[0] + '0' + temp[1:]favorite_color.append(temp)fig, ax = plt.subplots()# 画柱状图,颜色为使用较多的弹幕颜色plt.bar([1, 2, 3, 4, 5, 6, 7], data_color.values, color=favorite_color)plt.title(anime_name + '弹幕颜色使用数量前七名')plt.xlabel('排名')plt.ylabel('使用该颜色的弹幕数量')# plt.show()fig.savefig(r'./Analysis/弹幕分析图片/' + anime_name + 'Color.png', transparent=True)  # 保存if __name__ == '__main__':# # 去重duplicate(files[0])# 每一期弹幕总数的变化折线图danmuSumPlot(files[0])# 发弹幕总数TOP20的用户柱状图danmuUserTopBarh(files[0])# 弹幕颜色直方图DM_color(files[0])# 每期弹幕密度变化图danmuDensityChange(files[0])# 每期的弹幕词云danmuWordCloud(files[0])# 每期的弹幕词云(jieba去词以后-带图片背景)danmuWordCloud_Img(files[0])

这边就贴一张结果图片当实例吧

最后鸣谢这篇文章对我的帮助:(1条消息) python大作业——B站弹幕数据爬取与分析_lkx_icy的博客-CSDN博客_python爬取b站弹幕并进行数据分析

这篇关于Python大作业——弹幕数据分析(获取url cid 弹幕 画出词云)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/182835

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

Anaconda 中遇到CondaHTTPError: HTTP 404 NOT FOUND for url的问题及解决办法

最近在跑一个开源项目遇到了以下问题,查了很多资料都大(抄)同(来)小(抄)异(去)的,解决不了根本问题,费了很大的劲终于得以解决,记录如下: 1、问题及过程: (myenv) D:\Workspace\python\XXXXX>conda install python=3.6.13 Solving environment: done.....Proceed ([y]/n)? yDownloa