原理
弹幕获取原理
-
弹幕是储存在特定的页面上,根据视频的‘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站弹幕统计")