1设计目的和内容
1.1设计目的
1、获取用户反馈和意见:
通过调研B站视频评论,可以了解用户对视频内容、主题或频道的反馈和意见。这有助于了解用户的喜好、兴趣和需求,为改进视频内容或发布更相关的内容提供指导。
2、挖掘用户需求和趋势:
通过分析B站视频评论数据,可以发现用户的需求和趋势。通过分析评论中的关键词、提及的话题、观点等,可以识别出用户感兴趣的内容,帮助指导新视频的制作和内容策划。
3、评估视频质量和受欢迎程度:
通过分析评论中的点赞数、回复数等指标,可以评估视频的受欢迎程度和用户对视频质量的评价。这有助于制定视频推广策略和提高视频质量,以吸引更多用户观看和参与。
4、发现潜在合作机会:
通过调研B站视频评论,可以了解用户对合作内容、品牌或产品的关注和讨论。这可以为寻找合作机会和合作伙伴提供线索,通过与相关领域的品牌或个人进行合作,扩大视频的影响力和观众群体。
5、监测竞争对手和行业动态:
通过分析B站视频评论,可以了解竞争对手的视频表现和用户反馈。这有助于了解行业的动态和趋势,帮助优化自身视频内容和策略,保持竞争优势。
6、支持决策和优化策略:
通过对B站视频评论的调研和分析,可以为决策提供数据支持和参考。例如,根据用户反馈和需求调整视频发布频率、主题选择、内容形式等,以更好地满足用户的期望和提升观众参与度。
总而言之,通过对B站视频评论的调研爬虫分析,可以获取用户反馈和需求,评估视频质量和受欢迎程度,发现合作机会,监测竞争对手和行业动态,以支持决策和优化视频策略,提升用户体验和视频内容的质量。
1.2设计内容
对B站视频评论的调研爬虫分析的设计内容可以包括以下几个方面:
1、确定目标:
明确需要爬取和分析的B站视频评论的方面,例如特定视频、频道、主题或关键词。
2、确定爬虫工具和技术:
选择合适的爬虫工具和技术来实现数据抓取。可以使用Python的爬虫框架,如Scrapy或BeautifulSoup,以及相关的网络请求库,如Requests。
3、登录和权限:
如果需要获取登录用户的评论数据或访问有限制的内容,可能需要实现登录功能或使用B站提供的API接口进行权限验证。
4、抓取视频信息:
使用B站的API接口获取目标视频的基本信息,包括视频标题、发布时间、播放量等。
5、抓取评论数据:
使用B站的API接口获取目标视频的评论数据,包括评论内容、评论时间、点赞数等。可以通过遍历分页获取所有评论数据。
6、数据分析和挖掘:
对清洗后的评论数据进行分析和挖掘。可以使用Python的数据分析库,如Pandas和NumPy,进行数据统计、关联分析、情感分析等。
7、可视化呈现:
使用Python的可视化库,如Matplotlib、Seaborn或Plotly,将分析结果以图表、词云等形式进行可视化展示,使得数据更具可读性和可理解性。
2 设计思路
2.1首先思考我应该用哪些包,然后再配置好相应的版本:
2.2选择要爬虫的视频和评论:
选择要爬虫的B站视频https://www.bilibili.com/video/BV1Fk4y1j79c/?spm_id_from=333.1007.tianma.2-1-3.click&vd_source=be7d1529d66156bec002e804f2bc9d6f
2.3第二步处理数据保存下来
将爬虫下来的数据保存成.csv文件,方便我们进行进一步调研
2.4第三部分数据分析
1.首先,我们导入所需的库,包括pandas用于数据处理,numpy用于数值计算
matplotlib用于数据可视化等。
2.接下来,我们加载数据。使用pandas的read_csv函数从CSV文件中读取数据,并将其存储在一个变量中。
3.在数据清洗和预处理阶段,我们可以执行多种操作。例如,处理缺失值,可以使用dropna函数删除含有缺失值的行,或使用fillna函数用特定值填充缺失值。另外,如果数据中存在重复值,可以使用drop_duplicates函数删除重复行。此外,我们还可以进行数据转换,例如将某一列的数据类型转换为整数或日期时间类型。
4.在进行数据分析之前,通常会进行探索性数据分析(EDA)。这包括生成数据的统计信息,如描述性统计信息,以及数据的可视化,如绘制直方图、散点图等。
5.在数据分析和建模阶段,我们可以进行各种操作。例如,根据需要进行数据聚合,可以使用groupby函数按照某一列进行分组并计算统计指标,如平均值。此外,我们可以使用各种数据建模技术,如线性回归、决策树、聚类等。在建立模型后,我们可以对模型进行评估,例如计算拟合优度、预测目标变量等。
2.5.最后效果展示
1.通过爬虫将数据存储下来
2.生成词云图非常直观的输出评论高频字眼
3.生成柱状图和饼状图来分析B站视频评论
3基本功能描述
3.1基本功能
实现了使用Selenium库进行B站视频评论的爬取,并将评论数据保存到CSV文件中。然后使用Pandas和其他相关库对评论数据进行了基本的数据分析和可视化。
具体功能描述如下:
1.使用Selenium库进行模拟浏览器操作,加载指定B站视频页面。
2.使用XPath表达式提取页面中的评论内容和评论时间。
3.将提取的评论内容和评论时间写入CSV文件中。
4.使用Pandas库读取CSV文件中的数据,并进行数据清洗和处理,例如替换字符、删除无用符号等。
5.使用正则表达式提取评论时间中的小时部分,并生成小时与评论数量的数据。
6.使用Pyecharts库绘制柱状图,展示不同时间段的评论数量。
3.2函数介绍
函数名 | 功能 |
csv.writer() | 初始化一个用于写入 CSV 文件的写入器对象。 |
w.writerow() | 将一行数据写入 CSV 文件。 |
Chrome() | 初始化一个 Chrome webdriver 实例。 |
在 Chrome webdriver 中加载网页。 | |
time.sleep() | 暂停程序执行指定的秒数。 |
etree.HTML() | 解析 HTML并返回ElementTree 对象。 |
xpath() | 根据 XPath 表达式选择 XML/HTML 文档中的节点。 |
chrome.execute_script() | 在当前页面的上下文中执行 JavaScript |
re.findall() | 在字符串中搜索所有匹配指定模式的结果,并返回一个匹配结果的列表。 |
pd.read_csv() | 将 CSV 文件读入 pandas DataFrame。 |
DataFrame['column_name'].apply() | 将函数应用于 DataFrame 的某一列的每个元素。 |
Bar() | 使用 pyecharts 库创建一个柱状图。 |
Bar.add_xaxis() | 设置柱状图的 x 轴数据。 |
Bar.add_yaxis() | 设置柱状图的 y 轴数据。 |
Bar.set_global_opts() | 设置柱状图的全局选项。 |
render() | 将图表渲染为 HTML 文件。 |
collections.Counter() | 统计列表中元素的出现次数。 |
WordCloud() | 使用 pyecharts 库创建一个词云图。 |
WordCloud.add() | 向词云图添加数据。 |
jieba.lcut_for_search() | 将中文文本分词成单词。 |
most_common() | 从 Counter 对象中返回最常见的元素及其计数。 |
Pie() | 使用 pyecharts 库创建一个饼图。 |
Pie.add() | 向饼图添加数据。 |
Pie.set_global_opts() | 设置饼图的全局选项。 |
4功能设计
4.1设计步骤
1.引入所需的模块和库:
从selenium.webdriver导入Chrome和Service类
从selenium.webdriver.common.by导入By类
从selenium.webdriver.support.ui导入WebDriverWait类
从selenium.webdriver.support导入expected_conditions模块
从lxml库导入etree模块
导入csv和time模块
2.打开一个CSV文件用于存储评论数据
3.初始化一个Chrome webdriver实例,并加载指定的URL。
4.设置等待时间,使页面有足够的时间加载和渲染。
5.进入循环,通过执行JavaScript代码将页面滚动到底部,以便加载更多评论。
6.使用XPath解析页面的HTML内容,提取评论和时间信息。如果提取到的评论数量超过了设定的阈值(这里是400),则进行数据提取和写入操作,并跳出循环。
7.将父级评论和子级评论的信息分别提取,并写入CSV文件。
8.使用pd.read_csv()函数读取CSV文件,并对数据进行处理。
9.使用正则表达式提取评论时间中的小时部分。
10.创建一个柱状图,设置X轴和Y轴数据,并设置图表标题和样式。
11.将柱状图渲染为HTML文件。
12.将所有评论合并为一个文本字符串,并进行分词处理。
13.统计分词后的词频,并取前200个最常见的词汇。
14.创建一个词云图,设置数据和图形样式,并将其渲染为HTML文件。
15.组合时间段和评论数数据,并创建一个饼图,设置图表标题和样式,并将其渲染为HTML文件。
4.2系统开发工具
系统开发平台:python.3.8.3 PyCharm
系统开发语言:python
4.3数据格式
爬虫生成.csv的评论时间和评论内容的表格
最终生成407条数据
4.4 结果展示
1.通过爬虫将数据存储下来
在Excel打开,如前文;
2 .生成词云图非常直观的输出评论高频字眼
3.生成柱状图和饼状图来分析B站视频评论
5 关键功能
5.1 通过爬虫将数据存储下来:
f = open(file='replies.csv',mode='w',encoding='utf-8',newline='')
w = csv.writer(f)
w.writerow(['评论','时间'])
url = "https://www.bilibili.com/video/BV1Fk4y1j79c/?spm_id_from=333.1007.tianma.2-1-3.click&vd_source=be7d1529d66156bec002e804f2bc9d6f"
s = Service(executable_path='chromedriver.exe')
chrome = Chrome(service=s)
chrome.get(url=url)
chrome.implicitly_wait(10)
time.sleep(20)
while True:
chrome.execute_script('window.scrollTo(0,document.body.scrollHeight)')
chrome.implicitly_wait(10)
time.sleep(random.uniform(1,10))
html = etree.HTML(chrome.page_source)
p = html.xpath('//span[@class="reply-content"]')
if(len(p) > 400):
# 父级
tt = html.xpath('//div[@class="root-reply"]//span[@class="reply-time"]')
pp = html.xpath('//div[@class="root-reply"]//span[@class="reply-content"]')
for t,p in zip(tt,pp):
message = p.xpath(".//text()")
ctime = t.xpath(".//text()")
w.writerow([message,ctime])
print(f"\t获取到数据{[message,ctime]}")
# 子级
tt = html.xpath('//div[@class="sub-reply-container"]//span[@class="sub-reply-time"]')
pp = html.xpath('//div[@class="sub-reply-container"]//span[@class="reply-content"]')
for t,p in zip(tt,pp):
message = p.xpath(".//text()")
ctime = t.xpath(".//text()")
w.writerow([message,ctime])
print(f"\t获取到数据{[message,ctime]}")
break
功能特色:
(1)数据爬取:代码使用Selenium库模拟浏览器行为,访问指定的URL,并通过滚动页面等操作获取网页中的评论数据。爬取的评论数据包括父级评论和子级评论。
(2)数据存储:代码使用CSV文件来存储爬取到的评论数据。通过创建CSV文件并使用csv.writer对象,可以将评论内容和时间写入CSV文件的各行。
技术特色:
1.使用Selenium库:Selenium是一个功能强大的Web自动化测试工具,可以模拟用户在浏览器中的交互行为。这段代码利用Selenium的Chrome webdriver模块实现了自动化操作浏览器,从而实现了网页的加载、滚动、数据提取等功能。
2.使用XPath解析HTML:代码使用lxml库中的etree模块,结合XPath表达式,对HTML文档进行解析。通过XPath选择器,可以准确定位到需要提取的评论内容和时间,并进行提取操作。
3.隐式等待和固定等待:代码使用了Selenium的隐式等待和固定等待。通过设置chrome.implicitly_wait(10),代码将等待10秒钟,以确保页面中的元素完全加载。此外,使用time.sleep(random.uniform(1,10))实现固定时间的等待,以模拟用户的自然操作行为。
4.采用分级提取:代码通过XPath选择器分别提取父级评论和子级评论的内容和时间。分级提取的方式可以更好地组织和管理不同层次的评论信息,并将其写入CSV文件中。
5.2 词云图:
def get_text():
text = ""
for i in [j for j in dataset['评论']]:
text = str(text)
i = str(i)
text = text + i
return text.replace('【', '').replace('】', '').replace('/', '').replace('_', '').replace(' ', '')
text = get_text()
text_list = jieba.lcut_for_search(text)
word_counts = collections.Counter(text_list)
word_counts_top50 = word_counts.most_common(200)
wordcloud = WordCloud(init_opts=opts.InitOpts(width='600px', height='500px'))
wordcloud.add(series_name='评论词云图', data_pair=word_counts_top50, shape='star')
wordcloud.render('./img/热词词云.html')
功能特色:
1.词云展示:代码利用Pyecharts库中的WordCloud模块实现了词云图的生成。词云图以评论内容为数据源,通过统计词频并展示高频词汇在图表中的大小,形成直观的词云图形。
2.分词处理:代码使用了jieba库进行中文文本的分词处理,将评论内容按照一定规则切分成单个词语,以便后续统计词频。
3.词频统计:代码利用collections库的Counter类,对分词后的词语列表进行词频统计。通过统计每个词语在评论中出现的频次,得到各个词语的词频信息。
技术特色:
1.Pyecharts库:Pyecharts是基于Echarts的Python可视化库,能够方便地生成各种图表。这段代码利用Pyecharts中的WordCloud模块,提供了生成词云图的功能。
2.数据处理:代码通过对评论内容进行分词处理,将文本数据转化为可进行词频统计的格式。使用jieba库进行分词处理,将文本切分成单个词语列表。
3.词频统计与可视化:代码利用Counter类进行词频统计,并选取词频最高的前200个词语作为词云图的展示数据。通过调整词语在词云图中的大小和形状,反映不同词语的重要性和出现频次。
5.3 获取网页
url = "https://www.bilibili.com/video/BV1Fk4y1j79c/?spm_id_from=333.1007.tianma.2-1-3.click&vd_source=be7d1529d66156bec002e804f2bc9d6f"
s = Service(executable_path='chromedriver.exe')
chrome = Chrome(service=s)
chrome.get(url=url)
功能特色:
1.网页获取:使用Selenium库中的Chrome WebDriver模块,通过创建一个Chrome实例并指定驱动程序的路径,可以实现对指定网页的访问和数据获取。代码中使用了Chrome WebDriver加载指定的URL,并获取网页的源代码。
技术特色:
1.Chrome WebDriver:Chrome WebDriver是Selenium针对Chrome浏览器的驱动程序,通过与Chrome浏览器的通信,实现对浏览器的控制和操作。代码中使用Chrome WebDriver创建了一个Chrome实例,并通过指定URL进行网页访问。
5.4 柱状图和饼状图:
柱状图代码:
bar = (
Bar(init_opts=opts.InitOpts(width="1000px", height="500px"))
.add_xaxis(x_li)
.add_yaxis('次数', y_li, bar_width=30, color='blue', label_opts=opts.LabelOpts(formatter="({c}次)"))
.set_global_opts(title_opts=opts.TitleOpts("时间段评论数", padding=[10, 4, 5, 90],item_gap=5, title_textstyle_opts=opts.TextStyleOpts(color='#4F4F4F', font_size=18)))
)
bar.render('./img/时间段评论数bar.html')
饼状图代码:
li = [z for z in zip(x_li, y_li)]
pie = Pie(init_opts=opts.InitOpts(width="600px", height="500px"))
pie.add("时间段评论数饼图", data_pair=li, label_opts=opts.LabelOpts(formatter="次数:{b}({c}次)"),
radius=[30, 200], center=['50%', '50%'], rosetype="area")
pie.set_global_opts(
title_opts=opts.TitleOpts(title='时间段评论数', title_textstyle_opts=opts.TextStyleOpts(color='#4F4F4F', font_size=16)),
legend_opts=opts.LegendOpts(is_show=False)
)
pie.render('./img/时间段评论数pie.html')
柱状图功能特色:
1.使用pyecharts库中的Bar模块,可以绘制柱状图。代码中通过add_xaxis和add_yaxis方法设置x轴和y轴数据,并使用set_global_opts方法设置图表标题和样式。
2.使用opts模块中的InitOpts和TitleOpts等类,可以设置图表的初始化参数和标题参数,包括图表大小、标题内容、字体样式等。
通过render方法将生成的柱状图保存为HTML文件。
饼状图功能特色:
1.使用pyecharts库中的Pie模块,可以绘制饼状图。代码中通过add方法添加饼状图的数据和配置项,并使用set_global_opts方法设置图表标题和样式。
设置饼状图的半径、中心位置和展示方式等参数,例如radius、center和rosetype。
2.通过render方法将生成的饼状图保存为HTML文件。
技术特色:
1.pyecharts库:pyecharts是一个基于Echarts库的Python图表绘制库,可以方便地使用Python语言生成各种交互式图表。代码中使用pyecharts库的Bar和Pie模块,通过调用相应的方法和设置参数,实现了柱状图和饼状图的绘制。
2.opts模块:pyecharts库中的opts模块提供了一系列的选项类,可以对图表的各种参数进行配置和定制,包括图表标题、标签样式、图表大小等。
6 结论与心得体会
在完成这个Python爬虫并对数据进行分析和生成词云图的大作业过程中,我积累了许多宝贵的经验和体会。下面是我对整个项目的总结和心得体会:
1.项目背景和目标:
在开始项目之前,明确了项目的背景和目标是非常重要的。了解项目的背景和目标可以帮助我更好地定位问题和设计解决方案。在这个项目中,我需要使用Python爬虫获取数据,并对数据进行分析和可视化,目标是生成词云图来展示关键词的频率分布。
2.数据收集与处理:
数据是进行分析和可视化的基础,因此数据的收集和处理是非常关键的一步。我使用Python编写了爬虫程序,通过请求网页并解析HTML获取需要的数据。在处理数据时,我使用了适当的数据结构和算法来清洗和整理数据,以便后续的分析和可视化操作。
3.数据分析与可视化:
对数据进行分析和可视化是为了从数据中提取有意义的信息并以更直观的方式展示出来。在这个项目中,我使用了Python的数据分析库(如Pandas、NumPy)和可视化库(如Matplotlib、WordCloud)来进行数据分析和生成词云图。通过对数据进行统计分析和可视化展示,我能够更好地理解数据的特征和趋势。
4.项目挑战与解决方案:
在项目的过程中,我遇到了一些挑战,例如网页的反爬虫机制、数据的缺失和异常值等。为了克服这些挑战,我进行了深入的研究和学习,并采用了一些解决方案,例如使用代理IP解决反爬虫问题,使用数据插补方法处理数据的缺失值等。
5.学习与提升:
在完成这个项目的过程中,我不仅巩固了Python编程和数据处理的技能,还学到了许多新的知识和技巧。通过实践和探索,我对爬虫技术、数据分析和可视化有了更深入的理解,并且提升了自己的问题解决能力和学习能力。
通过这个项目,我深刻体会到了实践的重要性。只有在实际项目中才能真正理解和应用所学的知识,发现问题并解决问题。此外,良好的项目规划和组织能力也对项目的顺利进行起到了重要作用。
总而言之,这个Python爬虫与数据分析的大作业是一次非常有价值的经历。通过这个项目,我不仅提升了自己的技术能力,还增加了对数据分析和可视化的实践经验。我相信这些经验将对我的未来学习和职业发展产生积极的影响。
7 代码附录
7.1 总文件.py
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree
import csv
import time
import random
f = open(file='replies.csv',mode='w',encoding='utf-8',newline='')
w = csv.writer(f)
w.writerow(['评论','时间'])
url = "https://www.bilibili.com/video/BV1Fk4y1j79c/?spm_id_from=333.1007.tianma.2-1-3.click&vd_source=be7d1529d66156bec002e804f2bc9d6f"
s = Service(executable_path='chromedriver.exe')
chrome = Chrome(service=s)
chrome.get(url=url)
chrome.implicitly_wait(10)
time.sleep(20)
while True:
chrome.execute_script('window.scrollTo(0,document.body.scrollHeight)')
chrome.implicitly_wait(10)
time.sleep(random.uniform(1,10))
html = etree.HTML(chrome.page_source)
p = html.xpath('//span[@class="reply-content"]')
if(len(p) > 400):
# 父级
tt = html.xpath('//div[@class="root-reply"]//span[@class="reply-time"]')
pp = html.xpath('//div[@class="root-reply"]//span[@class="reply-content"]')
for t,p in zip(tt,pp):
message = p.xpath(".//text()")
ctime = t.xpath(".//text()")
w.writerow([message,ctime])
print(f"\t获取到数据{[message,ctime]}")
# 子
tt = html.xpath('//div[@class="sub-reply-container"]//span[@class="sub-reply-time"]')
pp = html.xpath('//div[@class="sub-reply-container"]//span[@class="reply-content"]')
for t,p in zip(tt,pp):
message = p.xpath(".//text()")
ctime = t.xpath(".//text()")
w.writerow([message,ctime])
print(f"\t获取到数据{[message,ctime]}")
break
7.2 制图.py
import pandas as pd
from pyecharts.charts import Pie,WordCloud,Bar,Geo
from pyecharts import options as opts
from pyecharts.globals import ThemeType
import jieba
import matplotlib.pyplot as plt
# from wordcloud import WordCloud
# 绘制
dataset = pd.read_csv('replies.csv')
dataset['时间'] = dataset['时间'].apply(lambda x: x.replace("'",'').replace('[','').replace(']','').replace("'",''))
dataset['评论'] = dataset['评论'].apply(lambda x: x.replace('[','').replace(']','').replace('!','').replace(',','').replace('。',''))
dataset.head()
import re
# 2023-05-18 14:29
def xiaoshi(x):
y = re.findall("(\d+):",str(x))
y.append('01')
l = y[0]
return l
dataset['小时'] = dataset['时间'].apply(xiaoshi)
# dataset['小时'].apply(lambda x: int(str(x).replace("'",'').replace('[','').replace(']','').replace("'",'')))
dataset.head()
x_li = [i + "时" for i in dataset.groupby('小时')['小时'].count().index]
y_li = [i for i in dataset.groupby('小时')['小时'].count()]
#polar_type.add('极坐标图',data=data,type_='line')
bar =(
Bar(init_opts=opts.InitOpts(width="1000px", height="500px")) # 主题风格 ,bg_color='#E8E8E8'
# x轴和y轴数据
.add_xaxis(x_li)
.add_yaxis('次数',y_li,bar_width=30,color='blue',label_opts=opts.LabelOpts(formatter="({c}次)"))
# .add_yaxis("Python趣味案例编程", [1567, 988, 2270,3900, 2750, 3600])
# 设置图表标题
.set_global_opts(title_opts=opts.TitleOpts("时间段评论数", # 主标题
padding=[10,4,5,90], # 标题内边距
# subtitle='价位手机', # 副标题
item_gap=5, # 主标题与副标题之间的间距
# 主标题字体颜色和大小
title_textstyle_opts=opts.TextStyleOpts(color='#4F4F4F',font_size=18)
))
)
bar.render('./img/时间段评论数bar.html')
import collections #计算词频
# 词云图
def get_text():
text = ""
for i in [ j for j in dataset['评论']]:
text = str(text)
i = str(i)
text = text + i
return text.replace('【','').replace('】','').replace('/','').replace('_','').replace(' ','')
text = get_text()
text_list = jieba.lcut_for_search(text)
len(text_list)
# 统计词频
word_counts = collections.Counter(text_list)
# 取值前五十
word_counts_top50 = word_counts.most_common(200)
wordcloud = WordCloud(init_opts=opts.InitOpts(width='600px',height='500px')) # ,bg_color='#E8E8E8'
# 词云图轮廓,有 'circle', 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star' 可选
wordcloud.add(series_name='评论词云图',data_pair=word_counts_top50,shape='star')
wordcloud.render('./img/热词词云.html')
li = [z for z in zip(x_li,y_li)]
pie = Pie(init_opts=opts.InitOpts(width="600px", height="500px")) # ,bg_color='white'
pie.add("时间段评论数饼图",data_pair=li,label_opts=opts.LabelOpts(formatter="次数:{b}({c}次)"),radius=[30, 200],center=['50%', '50%'], rosetype="area")
# pie.render('img\价格区间.html')
pie.set_global_opts(
title_opts=opts.TitleOpts(title='时间段评论数',# pos_left='400', pos_top='0',
title_textstyle_opts=opts.TextStyleOpts(color='#4F4F4F', font_size=16)),
legend_opts=opts.LegendOpts(is_show=False)
)
pie.render('./img/时间段评论数pie.html')