【python爬虫专项(25)】新型冠状病毒肺炎B站视频弹幕数据爬并做数据词云展示

1、查看要爬取页面

打开B站网址,输入“新型冠状病毒肺炎”关键字,显示界面如下:
在这里插入图片描述

2、确定爬虫逻辑

查看网页的内容后,一个网址页面下20个视频,这里只采集20页的视频数据(共400个视频),因为是出现的视频按照点击量进行排序的,所以再往后的视频爬取意义就不大了,因此基本爬虫逻辑如下:

【分页网址的url采集】——> 【单个视频url的采集】——> 【进入视频播放页面获取数据信息】——> 【打开存放弹幕的网页】 ——> 【按照要求爬取数据并存放到数据库】

函数式编程:
1)函数式编程
函数1:get_outer_urls(n) → 【分页网址url采集】
        n:爬取页数
        结果:得到分页网址的list

函数2:get_inner_urls(ui,d_h,d_c) → 【视频页面url采集】
        ui:分页网址
        d_h:user-agent信息
        d_c:cookies信息
        结果:得到存放单个视频页面的list

函数3:get_data(ui,d_h,d_c,table) → 【视频页面数据采集 / cid信息 / 弹幕xml数据采集】
        ui:视频页面网址
        d_h:user-agent信息
        d_c:cookies信息
        table:mongo集合对象

3、实战操作
步骤一、前期准备并封装第一个函数

1)导入相关的库,和设置代码分开标识
在这里插入图片描述
2)分析网页的规律,查看网页的2-4页(一般选取2-4就可以看出规律),网址如下:

u2 = https://search.bilibili.com/all?keyword=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E&order=click&duration=0&tids_1=0&page=2
u3 = https://search.bilibili.com/all?keyword=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E&order=click&duration=0&tids_1=0&page=3
u4 = https://search.bilibili.com/all?keyword=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E&order=click&duration=0&tids_1=0&page=4
......

通过2-4页网址的梳理,可以看出分页网址的规律,也就是最后面的“page=”之后数字发生变化,而且对应着具体的页码,那么获取前二十页的分页网址,就可以使用下面的方式:

urllist = []
for i in range(1,21):
    ui = f"https://search.bilibili.com/all?keyword=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E&order=click&duration=0&tids_1=0&page={i}"
    urllist.append(ui)
    
print(urllist)

输出结果为:(这里只截取前五页的网址)
在这里插入图片描述
3) 封装第一个函数

def get_outer_urls(n):
    '''
    【分页网址url采集】
    n:爬取页数
    结果:得到分页网页的list
    '''
    lst = []
    for i in range(1,21):
        ui = f"https://search.bilibili.com/all?keyword=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E&order=click&duration=0&tids_1=0&page={i}"
        lst.append(ui)
    
    return(lst)

urllst = get_outer_urls(20)
print(urllst)

输出结果和上面的一致

步骤二、设置请求头headers和登录信息cookies

这一步需要用户登录,没有账号的话,需要进行注册,cookies和headers(每个人的cookies和headers应单独设置)的获取方式如下,

文字详述: 以上面的登录后的网页界面为例,鼠标右键检查,然后选择右边标签Network,然后刷新一下该网页,这时候在右方Doc下面的Name菜单栏下会出现一个新的信息,选择第一个文件,然后拉到底,就可以找到cookies和headers的信息。

步骤归纳:【登录的页面】–> 【右键检查】–> 【Network】–> 【刷新】–> 【Doc下面的Name菜单栏】–> 【点击第一个文件下拉到底】–> 【Request Headers下】

图示
在这里插入图片描述
查找到headers和cookies之后,将其写入到字典中储存,如下(代码在spyder里运行)

dic_headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36"}

cookies = "_uuid=3D3C1683-5F16-D3EC-36E2-5967E731F7DA81323infoc; buvid3=3EB2F2F9-8EE3-4AFE-B3D6-7620A3B2E636155823infoc; LIVE_BUVID=AUTO4015671567822432; sid=bj42fy4m; CURRENT_FNVAL=16; stardustvideo=1; rpdid=|(umYuYRkm~|0J'ulY~ul~JlY; UM_distinctid=16ce1f17c989db-0c9243ec350826-e343166-144000-16ce1f17c99a18; CURRENT_QUALITY=0; DedeUserID=38449436; DedeUserID__ckMd5=272068a4511232d7; SESSDATA=3a11597f%2C1583975698%2C7bfdfc21; bili_jct=d8d63e8aa5a2eb9adf9f30698873d271; INTVER=1; arrange=matrix"
dic_cookies = {}
for i in cookies.split("; "):
	dic_cookies[i.split("=")[0]] = i.split("=")[1]

print(dic_headers)
print(dic_cookies)

输出结果如下:
在这里插入图片描述

步骤三、网页信息请求和网页初解析

首先尝试进行网页信息请求(以搜索关键词显示的第一个网页为例),代码如下

url = 'https://search.bilibili.com/all?keyword=%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92%E8%82%BA%E7%82%8E&order=click&duration=0&tids_1=0'
r = requests.get(url,headers = dic_headers, cookies = dic_cookies)
print(r)

输出结果为:<Response [200]> (说明网站信息可以正常访问,接下来进行页面的解析)

在网页界面鼠标右键,选择检查,可以发现,搜到的视频都是在【ul】标签下的【li】标签里面,如下
在这里插入图片描述
那么代码实现视频信息的获取如下:

soup = BeautifulSoup(r.text, 'lxml')
lis = soup.find("ul",class_ = "video-list clearfix").find_all("li")
print(lis[0])

输出的结果为:(这里以第一个视频为例,输出结果)
在这里插入图片描述
接着就可以获取视频的url、标题、上传时间和作者信息等数据,但是由于弹幕信息必须要进入视频的播放界面才可以获取到,因此在这一步只需要获取视频url即可,其余的信息在视频播放界面的网页上获取,通过上面的输出可以发现,视频网址放在里【a】标签下
在这里插入图片描述
代码实现视频url的获取如下:

inner_url = lis[0].a['href']
print(inner_url)

输出的结果为:(发现最前面少了https:,在封装函数的时候需要加上)
‘//www.bilibili.com/video/av84850049?from=search’

步骤四、封装第二个函数

上面实现了单个视频url的获取,接下来只需要进行遍历循环并把结果储存到列表即可,也就是封装第二个函数的要求,代码如下

def get_inter_urls(ui,d_h,d_c):
    '''
    【视频页面url采集】
    ui:视频信息网页url
    d_h:user-agent信息
    d_c:cookies信息
    结果:得到一个视频页面的list
    '''
    ri = requests.get(ui, headers = d_h, cookies = d_c)
    soupi = BeautifulSoup(ri.text, 'lxml')
    lis = soupi.find('ul',class_="video-list clearfix").find_all('li')
    lst = []
    for li in lis:
        lst.append('https:' + li.a['href'])
    return lst

url_1 = urllst[0]
print(get_inter_urls(url_1,dic_headers,dic_cookies))

输出结果为:(以第一页为例,可以输出该页的20个视频的url)
在这里插入图片描述

步骤五、网页深度解析(获取标题、时间和弹幕等)并将数据存入数据库

1) 获取标题
和之前的网页初解析一样,找到标题所对应的的标签信息,如下
在这里插入图片描述
代码实现如下:

url_1 = urllst[0]
inner_lst = get_inter_urls(url_1,dic_headers,dic_cookies)

r = requests.get(inner_lst[0],headers = dic_headers, cookies = dic_cookies)
soup = BeautifulSoup(r.text, 'lxml')
title = soup.h1['title']
print(title)

输出结果如下:
在这里插入图片描述
2) 获取上传时间
上传时间所对应的标签信息如下,信息在【div class=‘video-data’】标签下的【span】里面
在这里插入图片描述
代码实现如下:

upload_time = soup.find("span", class_ = "a-crumbs").next_sibling.text
print(upload_time)

输出的结果为:
在这里插入图片描述
3) 获取作者
作者对应的标签信息如下,名称在【div class=‘name’】下的第一个【a】标签下
在这里插入图片描述
代码实现如下:

author = soup.find("div", class_ = 'name').a.text
print(author)

输出的结果为:
在这里插入图片描述
4) 获取弹幕数据
① 解析一下cid
首先要从 B 站弹幕的说起,B 站视频的 ID 名字是 cid,一个 AV (视频)号下如果有多个分 P,就会占用多个 cid,cid 可以看做是视频的唯一 ID,通过这个 ID ,我们可以读取到 B 站的弹幕格式为 comment.bilibili.com/[cid].xml,在一开始给出的弹幕网址就为:https://comment.bilibili.com/84682646.xml

比如在第一个视频的网页界面点击鼠标右键查看源代码,然后搜索“cid”,就会发现相关的信息
在这里插入图片描述
复制"cid":后的数字查看一下这个信息在“检查”界面对应的标签的信息是怎么样的,搜索如下,可以看出都是在【script】标签下面
在这里插入图片描述
② cid 数据采集
对比“源代码"和"检查"页面,发现可以很好的获取cid的方式是通过在源代码窗口下查找,因为这里面的数据直接以字典的形式存储的,而如果再"检查"界面进行匹配标签,在来查找内容就显着很复杂,代码如下

cid = re.search(r'"cid":(\d*),', ri.text).group(1)
print(cid)

输出的结果为:
在这里插入图片描述
③ 弹幕信息采集
这里只需要将对应位置的数字换成cid信息即可,然后尝试获取该cid对应的url下面的内容(注意乱码的解决方式)

cid = re.search(r'"cid":(\d*),', r.text).group(1)
cid_url = f"https://comment.bilibili.com/{cid}.xml"
r2 = requests.get(cid_url)
r2.encoding = r2.apparent_encoding
soup2 = BeautifulSoup(r2.text, 'lxml')
print(soup2)

输出结果为:(截取部分片段)
在这里插入图片描述
检验能否获取该页面正常数据

dmlst = re.findall(r'<d.*?/d>',r2.text)
print(dmlst)

输出的结果为:(截取部分片段)
在这里插入图片描述
弹幕的标签信息全部存储到了dmlst里面了,接下来是提取里面的内容,顺便把之前的内容也写入到字典里面

for dm in dmlst:
    dic = {}
    dic['标题'] = title
    dic['上传时间'] = upload_time
    dic['cid'] = cid
    dic['作者'] = author
    dic['弹幕内容'] = re.search(r'>(.*)<',dm).group(1)
    dic['其他信息'] = re.search(r'p="(.*)">',dm).group(1)
    print(dic)

输出结果为:(截取部分)
在这里插入图片描述
至此,就把相应的数据全部储存在字典里面了,接下来就是配置数据库和封装第三个函数了

步骤六、配置数据库和封装第三个函数

1) 配置数据库

import pymongo
myclient = myclient = pymongo.MongoClient("mongodb://localhost:27017/")
db = myclient['冠状病毒弹幕数据']
datatable = db['data']

上述代码实现数据库的创建及命名,以及存放数据表格的创建

2)封装第三个函数,并将数据写入到数据库

只需要将每次生成的dic直接插入到创建的数据表格中即可,为了可视化储存过程,可以进行计数统计

def get_data(ui,d_h,d_c,table):
    '''
    ui:视频页面网址
    d_h:user-agent信息
    d_c:cookies信息
    table:mongo集合对象
    '''
    ri = requests.get(url = ui, headers = d_h, cookies = d_c)
    soupi = BeautifulSoup(ri.text, 'lxml')
    #title = soupi.find(id = "viewbox_report").span.text
    title = soupi.h1['title']
    upload_time = soupi.find("span", class_ = "a-crumbs").next_sibling.text
    #upload_time = re.search(r'(20.*\d)',soupi.find("div",class_ ="video-data").text)
    cid = re.search(r'"cid":(\d*),', ri.text).group(1)
    cid_url = f"https://comment.bilibili.com/{cid}.xml"
    r2 = requests.get(cid_url)
    r2.encoding = r2.apparent_encoding
    dmlst = re.findall(r'<d.*?/d>',r2.text)
    
    n = 0
    for dm in dmlst:
        dic = {}
        dic['标题'] = title
        dic['上传时间'] = upload_time
        dic['cid'] = cid
        dic['作者'] = author
        dic['弹幕内容'] = re.search(r'>(.*)<',dm).group(1)
        dic['其他信息'] = re.search(r'p="(.*)">',dm).group(1)
        table.insert_one(dic)
        n += 1 
    return n 

最后运行代码:

inner_urllst = []
error_lst = []
for outer_url in urllst:
    try:
        inner_urllst.extend(get_inter_urls(outer_url,dic_headers,dic_cookies))
        print("已成功获取{}条视频数据".format(len(inner_urllst)))
    except:
        error_lst.append(outer_url)
        print("获取视频信息失败,网址为:",outer_url)
                

count = 0
for u in inner_urllst:
    try:
        count += get_data(u,dic_headers,dic_cookies,datatable)
        print('数据采集并存入成功,总共采集{}条数据'.format(count))
    except:
        error_lst.append(u)
        print('数据采集失败,数据网址为:',u)	

输出的结果为:
在这里插入图片描述
数据库里面的数据
在这里插入图片描述

数据分析

首先将保存在MongoDB数据库的数据导出,如下
在这里插入图片描述
接着就可以就可以读取桌面的csv文件了,代码如下:

import pandas as pd
    
df = pd.read_csv(r"C:\Users\86177\Desktop\result.csv")
data = df['弹幕内容']
data.value_counts()[:20]

输出的结果为:(按照字频选择前二十进行输出)
在这里插入图片描述
最后将结果进行词云展示;

import pandas as pd
from wordcloud import WordCloud
    
df = pd.read_csv(r"C:\Users\86177\Desktop\result.csv")
data = df['弹幕内容']
txt = " ".join(data.tolist())
txt = txt.replace("哈","")
wc = WordCloud(width=600, height=400).generate(txt)
wc.to_file('wordcloud.png')

输出的结果为:
在这里插入图片描述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值