Python获取并统计弹幕

原理

弹幕获取原理

  • 弹幕是储存在特定的页面上,根据视频的‘cid’可以获取页面位置,所以需要先获取视频的‘cid’,再打开弹幕页面,进而处理。

    其弹幕储存的页面url格式为: http://comment.bilibili.com/ cid .xml (网站一)

  • 那么如何根据BV号来确定cid呢?视频的很多数据都储存在某个特定网站,其中BV号就储存在其中

    其页面url为 https://api.bilibili.com/x/player/pagelist?bvid=(此处为BV号)&jsonp=jsonp (网站二)

  • 那么具体操作就很简单了,先打开网站二。从中获得cid,然后根据cid获得弹幕储存页面,之后爬取就可以了

爬虫部分

一个爬虫程序大体是这个样子:

import requests
myUrl = 'https://fanyi.baidu.com/sug'

myHeader = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36'
}
myDate = {
'kw' : 'love'
}

response = requests.post(url = myUrl, data = myDate, headers = myHeader)

其中,爬取页面数据,只是那个requests.post()函数,其他部分都是参数,其中,post是一种请求方式,还有一种,是get,它们两个有很大区别,在我们
写爬虫时,表现为写法不同,详细了解可以去百度一下QAQ。

  • url参数,即为目标网址。
  • data参数,即为发送的数据内容(可以理解为往目标页面的某个地方输入内容, 或者点击某个部分)
  • header参数,这个参数记录了这个数据包是由谁发起,使用什么浏览器的等内容

假如我们用的是Chrome浏览器,我们随便打开一个网址,右键,”检查“,”Network“部分,刷新页面,随便点一个,那就是我们数据包的样子。

我们先手动进行这个操作,那么header部分就是我们手动操作产生的,但是如果我们不做修改,直接用程序发包,那么这个header部分就会不一样,就有可能会被
网站识别,其中最主要部分就是这个’User-Agent’部分。

header部分
  • User-Agent是一个告诉网页,自己是通过什么方法(比如post,get)来访问的,如果网站发现是非人工来访问的,那么就会禁止,所以需要自己来“伪造”一下。

    • 方法一:自己手动上网页中,在“检查”中选中“network”,刷新一下,随便点一个,在“Reequest-Header”中就能找到User-Agent
    • 方法二: 直接伪造(目前正在开发)

    所以我们手动操作的时候,把User-Agent中的内容复制一下,放到自己设置的参数中

data部分

假如我们想要一个在一个页面中显示搜索某个内容得到的结果(或者点击一些内容),那么就要修改data部分了,那么改如何获取呢?

  • 首先我们在页面的搜索框(假设我们要搜索),搜索的时候打开”检查“部分,还是network部分,点击页面中的搜索时,就会产生很多数据包

  • 点击与搜索相关的数据包(可能需要找一下,可以试着找带有”search“相关的数据包),往下拉,一般在下面有一个”Query String Parameters“
    (会根据请求方式时get还是post而发生改变),我们可以根据里面的参数值是否有我们刚才输入的内容来判断。
    里面记录的就是 data内容,把它们复制下来粘贴到自己的data参数中即可

后续处理(BeautifulSoup)

我们是把整个页面的html对象爬取下来了,那么我们改如何储存它呢?

这时我们就用到了BeautifulSoup这个库,它能很好地帮助我们去处理爬取的网站页面。(详细内容可以百度搜索或者直接查看它的文档,这里只做简单说明QAQ)

由于爬取的页面返回的是byte形式,且是以utf-8格式编码的,所以我们要把它转化为unicode格式(具体见下面代码,详细可以去百度)

response = requests.get(url = dUrl, headers = myHeaders)
response.encoding='utf-8'    # 定义爬取的页面解码格式
content = response.content.decode(response.encoding) # 将转换后的结果赋给content
soup = BeautifulSoup(content, 'xml') # 第一个参数为读取的内容,第二个参数设置读取格式(读取xml格式的话,可能需要下载lxml库)
result = soup.find_all('d') # 观察发现,所有的弹幕都是在<p>标签内,这个操作会把所有的<p>标签内容放入list中

f = open("bilibili.txt", "w", encoding='utf-8')

barrage = {} # 弹幕及其数量
for i in result:   # 统计这个弹幕是否出现过以及数量
  if i.text in barrage:  # text方法会返回这个标签下的文字内容
    barrage[i.text] = barrage[i.text] + 1
  else:
    barrage[i.text] = 1


num = 0
keyWords = '' # 统计发送较多的弹幕

for txt, sum in sorted(barrage.items(), key=lambda barrage: barrage[1], reverse=True):  # 从小到大排序
  f.write(txt + ' : ' + str(sum))
  f.write('\n')
  if num > 4 :
    continue
  else:
    num = num + 1
    keyWords = keyWords + '  ' + txt
f.close()

完整代码:

from bs4 import BeautifulSoup
import requests
import json
import easygui as g
import snownlp


# b站弹幕是储存在特定的页面上,根据视频的‘cid’可以获取页面位置,所以需要先获取视频的‘cid’,再打开弹幕页面,进而处理

myUrl = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1No4y127Zk&jsonp=jsonp'

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

# 根据输入的bv号来搜索cid
# 可以先拿这个BV号试一下   BV1kK41137bj
bvNum = g.enterbox(msg='请输入视频的BV号(‘BV’也要输入的,例如:BV17p4y1z7hq)', title='b站弹幕统计')

myUrl = 'https://api.bilibili.com/x/player/pagelist?bvid=' + bvNum + '&jsonp=jsonp'

response = requests.get(url = myUrl, headers = myHeaders)

d = json.loads(response.text)
cid = d['data'][0]['cid']

# 获得了cid就可以去相应的页面来找全体弹幕

dUrl = 'http://comment.bilibili.com/'+ str(cid) +'.xml'

response = requests.get(url = dUrl, headers = myHeaders)
response.encoding='utf-8'
content = response.content.decode(response.encoding)
soup = BeautifulSoup(content, 'xml')

result = soup.find_all('d')

f = open("bilibili.txt", "w", encoding='utf-8')

barrage = {} # 弹幕及其数量
for i in result:
    if i.text in barrage:
        barrage[i.text] = barrage[i.text] + 1
    else:
        barrage[i.text] = 1


num = 0
keyWords = '' # 统计发送较多的弹幕

for txt, sum in sorted(barrage.items(), key=lambda barrage: barrage[1], reverse=True):  # 从小到大排序
    f.write(txt + ' : ' + str(sum))
    f.write('\n')
    if num > 4 :
        continue
    else:
        num = num + 1
    keyWords = keyWords + '  ' + txt
f.close()

print(keyWords)

g.msgbox(msg="统计完成!结果输出在这个文件夹下的bilibili.txt里!>_<" + "\n" + "发送较多的弹幕为:" +"\n" + keyWords,title="b站弹幕统计")


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值