2023软工K班个人编程任务

林展平102101432 2023-09-14 23:35:29

Github链接:https://github.com/jockerUtf-8/pythonSpider

一、PSP表格

Personal Soft ware process Stages预估耗时(min)实际耗时(min)
估计这个任务需要多长时间6001000
计划1060
开发40140
需求分析5050
生成设计文档5050
代码规范3060
具体设计3060
具体编码250400
代码复审2030
测试4050
报告4050
测试报告3030
计算工作量1010
事后总结1010

二、任务要求的实现

3.1 项目设计与技术栈。从阅读完题目到完成作业,这一次的任务被你拆分成了几个环节?你分别通过什么渠道、使用什么方式方法完成了各个环节?列出你完成本次任务所使用的技术栈。

一共拆成了3个部分,第一部分就是获取弹幕的url,由于之前没有python爬虫的经验,学了点基础课就开始上手了,查资料得知,把视频的地址的bilibili改成ibilibili,点进去才能找到弹幕的地址,所以我先寻找了300个视频的url,然后失败了好多次,最后才将视频地址找到,最后才是弹幕地址,其中我运用了xpath寻找到了视频的地址,也算是学会了很多第二部分就是处理弹幕内容,统计弹幕数量,我借助chatgpt的提示,采用字典匹配的模式处理文本中的每一行弹幕数据,最后将其倒序输出.第三部分则是数据的可视化表示我通过学习词云图的绘制方法以及excel的相关操作进一步完善数据。

3.2 爬虫与数据处理。说明业务逻辑,简述代码的设计过程(例如可介绍有几个类,几个函数,他们之间的关系),并对关键的函数或算法进行说明。

首先我导入了以下几个包:

import time
from selenium import webdriver#selenium的浏览器真实模拟器
from selenium.webdriver.common.by import By
import requests#request请求方便快捷
import re#正则表达式
import wordcloud#词云专属包
import jieba#处理文字专用包

接着就是找到前300个弹幕的url地址并将其写入文件:

if __name__ == '__main__':
    Link = []#记录300个视频的url
    count = 0
    proxy = {'http': '182.34.102.153:9999'}#我爬虫的次数太多了,ip被B站列入了黑名单,只能请求代理
    headers = {'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36'}
    # 搜索关键词后第一页的网页地址
    url = ['https://search.bilibili.com/all?keyword=%E6%97%A5%E6%9C%AC%E6%A0%B8%E6%B1%A1%E6%B0%B4%E6%8E%92%E6%B5%B7']
    for i in range(14):  # 每页是24个视频,至少要打开14页才能爬取到300个视频
        if (i > 0): url.append(url[0] + '&page=' + str(i + 1) + '&o=' + str(24 * i))  # 第二页以后每页地址的规律格式
    driver = webdriver.Chrome()
    for i in range(14):
        driver.get(url[i])
        time.sleep(1)  # 需要等待1秒,不然会因页面点击太快而出错
        if (i == 0):
            for j in range(24):
                response = driver.find_element(By.XPATH,'/html/body/div[3]/div/div[2]/div[2]/div/div/div/div[2]/div/div[' + str(j + 1) + ']/div/div[2]/a')  # 第一页中所有视频url的xpath规律格式
                link = response.get_attribute('href')  # 获取当前视频的url
                link = link.replace('bilibili', 'ibilibili')  # 弹幕信息在ibilibili的地址中
                Link.append(link)  # 收集url
                count += 1
        else:
            for j in range(24):  # 同第一页的代码同理,只是xpath的格式不同
                response = driver.find_element(By.XPATH,'/html/body/div[3]/div/div[2]/div[2]/div/div/div[1]/div[' + str(j + 1) + ']/div/div[2]/a')
                link = response.get_attribute('href')
                # response.click()
                link = link.replace('bilibili', 'ibilibili')
                Link.append(link)
                count += 1
                if (count > 300):  # 当获取的url达到300个时结束循环
                    break
    for i in range(300):
        response=requests.get(url=Link[i],headers=headers,proxies=proxy)#获取视频信息
        content = response.text#获取信息文本
        pattern = r'cid":"\d+"'#弹幕地址存储在信息文本中的cid中
        match = re.search(pattern, content)#以上述模式寻找信息
        cid=match.group()#group为匹配到的目标字符串
        cid=cid.lstrip('cid":"')
        cid=cid.rstrip('"')#去除边角
        url='https://api.bilibili.com/x/v1/dm/list.so?oid='+cid#拼凑出弹幕的地址
        print(url)
        response=requests.get(url=url,headers=headers)#请求弹幕内容
        response.encoding='utf-8'
        contentList=re.findall('<d p=".*?">(.*?)</d>',response.text)#提取有效信息
        for content in contentList:#写入弹幕.txt
            with open('弹幕.txt','a',encoding='utf-8')as fp:
                fp.write(content)
                fp.write('\n')

由于本人比较菜,我自己摸索出来的办法就是就是通过xpath的规律找到300个视频的url地址,然后找到每个视频的cid并生成对应弹幕的地址,并将他们下载进来,时间复杂度比较大.
部分弹幕.txt文件如下,显然,内容会有很多冗余:

img

然后就是将采集到的数据文件弹幕.txt中的弹幕逐行读取到字典中,统计每种弹幕的数量,并将其输出到另一个文件B站弹幕中:

with open('弹幕.txt','r',encoding='utf-8')as fp:
    lines=fp.readlines()#逐行读取文件
lineCount={}#建立空字典
for line in lines:#统计弹幕数
    if line not in lineCount:#如果不在字典中,就创建新的数据
        lineCount[line]=1
    else:
        lineCount[line]+=1#在字典中,就让次数加一
sortedDict = sorted(lineCount.items(),key=lambda x:x[1],reverse=True)#对字典进行降序排序
for i in range(len(sortedDict)):#循环每一个元组
    danmu=str(sortedDict[i])#转化为字符串后更好处理
    danmu=re.sub(r'[^\w\s,]','',danmu)
    danmu=danmu.replace('n, ',':')#对字典中的元素规范化之后再写入文件
    with open('B站弹幕.txt', 'a', encoding='utf-8') as fp:
        fp.write(danmu)
        fp.write('\n')

经过初步的处理,已经基本将数量统计出来了,但由于不同人输入格式的问题(比如有些人会多输入一些空格,不好识别)接下来可以用excel的合并计算的功能将冗余数据合并在一起,并且去除一些没有价值的弹幕信息。

img


经过excel处理之后就舒服多了:

img

制作词云图:

f=open('B站弹幕.txt',encoding='utf-8')
txt=f.read()
string=' '.join(jieba.lcut(txt))
print(type(string))
wc=wordcloud.WordCloud(
    width=700,#宽和高各700
    height=700,
    background_color='white',#背景白色
    scale=15,#规模
    font_path='STXINWEI.TTF'#字体
)
wc.generate(string)
wc.to_file('弹幕词云.png')

结果如下:

img

3.3 数据统计接口部分的性能改进。记录在数据统计接口的性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(例如可通过VS /JProfiler的性能分析工具自动生成),并展示你程序中消耗最大的函数。

我一共写了三个.py的文件分别为爬取弹幕.py,统计数据.py和制作词云.py,使用pycharm自带的性能分析工具得出的结果如下(由于篇幅有限,只展示耗时最长的爬取弹幕的文件的结果):

img

3.4 数据结论的可靠性。介绍结论的内容,以及通过什么数据以及何种判断方式得出此结论

以下这些是我通过将数量最多的100条弹幕让chatgp分析t得出的中国网友主流观点:

  • 坚决抵制日本排放核污染水:大部分网友都表示强烈反对日本将核污水排入海洋,认为这种行为对海洋生态环境和人类健康构成严重威胁。
  • 保护海洋、保护地球:很多网友强调了保护海洋和地球的重要性,认为即使日本不存在,也不能失去宝贵的海洋资源和地球环境。
  • 支持世界和平:一些网友表达了对世界和平的期望,希望各国能够通过对话和合作解决环境问题,而不是采取不负责任的行动。
  • 学习、加油、支持、笑死等情绪词汇也经常出现,显示了网友们对于这一问题的关注和讨论的热情。
3.5 数据可视化界面的展示。在博客中介绍数据可视化界面的组件和设计的思路。

在制作数据可视化图像词云图的过程中。由于wordcloud函数需要传入规范化的字符串,所以我用了jieba库中的lcut函数将从B站弹幕中读出来的内容变成一行一行的,以方便生成词云图,并在wordcloud函数中输入相应的参数如长宽,背景颜色等,制作完词云图后,我也用处理后的excel表格的前20行生成了旭日图表:

img

三、心得体会

在执行本次任务之前,我完全没学过爬虫,编程能力也很弱,但在这次实验中,我先学习了B站上的python爬虫的基本课程,然后上手实践,其中虽然遇到了许多困难,但在我的慢慢摸索和chatgpt的提示下,也算是圆满完成了,虽然和大佬们没法比,但对我自己来说已经是一个非常大的进步了,同时也让我意识到自身编程能力的不足,今后我也会更多地进行实操,学习更多的专业知识

...全文
38 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

117

社区成员

发帖
与我相关
我的任务
社区描述
2023福州大学软件工程K班
软件工程 高校 福建省·福州市
社区管理员
  • kevinkex
  • Devil angel
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧