python获取B站up主视频信息

这里记录一下爬取b站up主视频数据的过程

** 文章为2022年写的,中间可能有变化,总的思路还是这个**

1.为了爬去视频的播放量、视频名称、发布时间等数据,首先想到来到up主页的投稿区,然后再进行分析。

这里是爬取的up主:爬取up主

2.然后分析能否直接找到这些数据的json文件,如果找到了就可以直接分析,没找到就尝试爬去html然后再进行分析,下面就分析网站加载的数据:1

3.运气很好,分析之后找到了数据加载的来源,具体如下

1

分析数据可以得到:

  • aid:视频的唯一id
  • bvid:视频的唯一id,这里我觉得是和aid相同的意思
  • comment:视频评论量
  • created:视频发布的时间,可以用时间戳转换器转成我们熟悉的时间形式
  • description:作者对视频的描述
  • length:视频的时间长度
  • pic:视频的封面图片地址
  • play:播放量
  • title:视频的名字
  • video_review:弹幕数
    知道了有数据,我们还要想怎么能爬取完所有的视频,接下来就分析这个数据来源的URL:第一页2
    第二页
    3

通过分析很容易知道pn=1就是控制页数的,这样我们通过构造pn=?就可以控制下载的页数,下面就开始编程实现了。

4.编码分析部分

4.1首先导入基本的模块

import requests #访问页面用
import time #暂停时间,爬取速度太快容易被发现,可能会出问题,所以需要暂停
import openpyxl #数据存储到excel中会用

4.2首先编写数据爬取的测试函数

def get_Requests():
    pg = 1 #一共有5页的内容
    # headers用来模拟是通过浏览器发起的get请求,在刚才分析url的Headers那儿找
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
    }
    
    for i in range(1,pg+1):
        # 通过构造每一页进行访问
        url = f"https://api.bilibili.com/x/space/arc/search?mid=501271968&ps=30&tid=0&pn={i}&keyword=&order=pubdate&jsonp=jsonp"
        res = requests.get(url=url, headers=headers)
        print(res.text)
get_Requests()

这里测试了一页,发现能把数据爬取下来,然后我们就可以继续编写下去,并完善,在这之前,需要先了解json的解析器,我用的是json-handle,一个浏览器的插件,作用是方便我们分析json的信息,样子如下:4

def get_Requests():
    pg = 5 #一共有5页的内容
    # headers用来模拟是通过浏览器发起的get请求,在刚才分析url的Headers那儿找
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
    }
    
    # 提前定义数据的列表,后面用来存储爬取的数据
    comment = [] # 评论数
    play = [] # 播放量
    pic = [] # 封面图
    description = [] # 描述
    title = [] # 标题
    created = [] # 上传时间
    length = [] # 视频长度
    video_review = [] # 弹幕量
    aid = []
    bvid = []
    
    for i in range(1,pg+1):
        # 通过构造每一页进行访问
        url = f"https://api.bilibili.com/x/space/arc/search?mid=501271968&ps=30&tid=0&pn={i}&keyword=&order=pubdate&jsonp=jsonp"
        # 通过url进行访问,并返回数据
        res = requests.get(url=url, headers=headers)
        # 如果有编码错误的问题,可以先解码
        res.enconding = 'utf-8'
        # 这一步因为我们得到了json文件,就可以直接用字典的形式访问到我们想要的数据
        res_dict = res.json()
        # 通过字典的方式,得到我们需要的数据
        for j in range(30): # 因为数据一次可以爬取20个,需要一个一个存储下来
            try: # 要用try的原因考虑到最后一页的数据可能不是有30个视频,就会报错
                # 通过append把数据存储在列表中
                comment.append(res_dict['data']['list']['vlist'][j]['comment'])
                play.append(res_dict['data']['list']['vlist'][j]['play'])
                pic.append(res_dict['data']['list']['vlist'][j]['pic'])
                description.append(res_dict['data']['list']['vlist'][j]['description'])
                title.append(res_dict['data']['list']['vlist'][j]['title'])
                created.append(res_dict['data']['list']['vlist'][j]['created'])
                length.append(res_dict['data']['list']['vlist'][j]['length'])
                video_review.append(res_dict['data']['list']['vlist'][j]['video_review'])
                aid.append(res_dict['data']['list']['vlist'][j]['aid'])
                bvid.append(res_dict['data']['list']['vlist'][j]['bvid'])
            except:
                pass # 出现问题直接pass掉不管
        # 至此,第一次的爬去完成,可以测试数据时候爬取时候成功
        # print(bvid)
        # 为了避免因为访问速度过快,这里没爬取一页暂停1s
        print("--第%d页爬取完成\n"%(i))
        time.sleep(1)
    # 此处数据全部爬取完成,下面将通过函数存储
    store_Data(comment, play, pic, description, title, created, length, video_review, aid, bvid)

承接上个函数,这里编写存储函数

def store_Data(comment, play, pic, description, title, created, length, video_review, aid, bvid):
    print("--开始存储")
    # 这里用到openpyxl,我先在本目录下创建了‘数据存储.xlsx’的文件用来存储
    wb = openpyxl.load_workbook('数据存储.xlsx')
    # 选择里面的第一个sheet就行
    sheet = wb.worksheets[0]
    # 这里先给数据信息取个名,放在第一行
    sheet['A1'] = 'bvid'
    sheet['B1'] = 'aid'
    sheet['C1'] = '视频标题' # title
    sheet['D1'] = '视频描述' # description
    sheet['E1'] = '上传时间' # created
    sheet['F1'] = '视频长度' # length
    sheet['G1'] = '弹幕数量' # video_review
    sheet['H1'] = '播放量' # play
    sheet['I1'] = '评论量' # comment
    sheet['J1'] = '封面图地址' # pic
    
    # 由于爬取的每个信息是一一相对的,而且列表长度也是一致的,所以通过len(xx)确定长度
    for i in range(len(aid)):
        # 注意此时i是从0开始的,而我们的数据在excel中是从第二行开始存储,所以+2
        sheet['A'+str(i+2)] = bvid[i]
        sheet['B'+str(i+2)] = aid[i]
        sheet['C'+str(i+2)] = title[i]
        sheet['D'+str(i+2)] = description[i]
        sheet['E'+str(i+2)] = created[i]
        sheet['F'+str(i+2)] = length[i]
        sheet['G'+str(i+2)] = video_review[i]
        sheet['H'+str(i+2)] = play[i]
        sheet['I'+str(i+2)] = comment[i]
        sheet['J'+str(i+2)] = pic[i]
    # 存取完成保存
    print("完成存储!")
    wb.save('数据存储.xlsx')

最后编写主函数,进行调用

if __name__ == "__main__":
    get_Requests()
--第1页爬取完成

--第2页爬取完成

--第3页爬取完成

--第4页爬取完成

--第5页爬取完成

--开始存储
完成存储!

查看excel,成功得到数据6

5.总结分析

  • 应该是可以通过输入mid(应该是用户名的意思)直接在主函数输入mid,然后就可以完成后面的
  • 应该可以通过找数据直接获取pn,而不用手动输入

为了通过输入mid和pn直接爬取,下面做一下相应的修改,mid可以在控制台alert(mid)

import requests #访问页面用
import time #暂停时间,爬取速度太快容易被发现,可能会出问题,所以需要暂停
import openpyxl #数据存储到excel中会用
import random #让暂停的时间间隔变得随机

def get_Requests(mid, pg):
    # headers用来模拟是通过浏览器发起的get请求,在刚才分析url的Headers那儿找
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
    }
    
    # 提前定义数据的列表,后面用来存储爬取的数据
    comment = [] # 评论数
    play = [] # 播放量
    pic = [] # 封面图
    description = [] # 描述
    title = [] # 标题
    created = [] # 上传时间
    length = [] # 视频长度
    video_review = [] # 弹幕量
    aid = []
    bvid = []
    
    for i in range(1,pg+1):
        # 通过构造每一页进行访问
        url = f"https://api.bilibili.com/x/space/arc/search?mid={mid}&ps=30&tid=0&pn={i}&keyword=&order=pubdate&jsonp=jsonp"
        # 通过url进行访问,并返回数据
        res = requests.get(url=url, headers=headers)
        # 如果有编码错误的问题,可以先解码
        res.enconding = 'utf-8'
        # 这一步因为我们得到了json文件,就可以直接用字典的形式访问到我们想要的数据
        res_dict = res.json()
        # 通过字典的方式,得到我们需要的数据
        for j in range(30): # 因为数据一次可以爬取20个,需要一个一个存储下来
            try: # 要用try的原因考虑到最后一页的数据可能不是有30个视频,就会报错
                # 通过append把数据存储在列表中
                comment.append(res_dict['data']['list']['vlist'][j]['comment'])
                play.append(res_dict['data']['list']['vlist'][j]['play'])
                pic.append(res_dict['data']['list']['vlist'][j]['pic'])
                description.append(res_dict['data']['list']['vlist'][j]['description'])
                title.append(res_dict['data']['list']['vlist'][j]['title'])
                created.append(res_dict['data']['list']['vlist'][j]['created'])
                length.append(res_dict['data']['list']['vlist'][j]['length'])
                video_review.append(res_dict['data']['list']['vlist'][j]['video_review'])
                aid.append(res_dict['data']['list']['vlist'][j]['aid'])
                bvid.append(res_dict['data']['list']['vlist'][j]['bvid'])
            except:
                pass # 出现问题直接pass掉不管
        # 至此,第一次的爬去完成,可以测试数据时候爬取时候成功
        # print(bvid)
        # 为了避免因为访问速度过快,这里没爬取一页暂停随机1~3s
        print("--第%d页爬取完成\n"%(i))
        time.sleep(random.randint(1,3))
    # 此处数据全部爬取完成,下面将通过函数存储
    store_Data(comment, play, pic, description, title, created, length, video_review, aid, bvid,mid)

def store_Data(comment, play, pic, description, title, created, length, video_review, aid, bvid,mid):
    print("--开始存储")
    # 这里用到openpyxl,我先在本目录下创建了‘数据存储.xlsx’的文件用来存储
    # wb = openpyxl.load_workbook('数据存储.xlsx')
    # 下面测试创建一个wb
    wb = openpyxl.Workbook()
    # 选择里面的第一个sheet就行
    sheet = wb.worksheets[0]
    # 这里先给数据信息取个名,放在第一行
    sheet['A1'] = 'bvid'
    sheet['B1'] = 'aid'
    sheet['C1'] = '视频标题' # title
    sheet['D1'] = '视频描述' # description
    sheet['E1'] = '上传时间' # created
    sheet['F1'] = '视频长度' # length
    sheet['G1'] = '弹幕数量' # video_review
    sheet['H1'] = '播放量' # play
    sheet['I1'] = '评论量' # comment
    sheet['J1'] = '封面图地址' # pic
    
    # 由于爬取的每个信息是一一相对的,而且列表长度也是一致的,所以通过len(xx)确定长度
    for i in range(len(aid)):
        # 注意此时i是从0开始的,而我们的数据在excel中是从第二行开始存储,所以+2
        sheet['A'+str(i+2)] = bvid[i]
        sheet['B'+str(i+2)] = aid[i]
        sheet['C'+str(i+2)] = title[i]
        sheet['D'+str(i+2)] = description[i]
        sheet['E'+str(i+2)] = created[i]
        sheet['F'+str(i+2)] = length[i]
        sheet['G'+str(i+2)] = video_review[i]
        sheet['H'+str(i+2)] = play[i]
        sheet['I'+str(i+2)] = comment[i]
        sheet['J'+str(i+2)] = pic[i]
    # 存取完成保存
    print("完成存储!")
    wb.save('数据存储'+'mid:'+str(mid)+'.xlsx')  

if __name__ == "__main__":
    mid = 2
    pn = 1 # 一共有多少页
    get_Requests(mid, pn) 
--第1页爬取完成

--开始存储
完成存储!
ls
[0m[01;34m数据[0m/  数据存储mid:2.xlsx  数据存储.xlsx  爬取b站up主数据.ipynb
cd 数据/
/home/alien/Desktop/passage/jupyter/爬取b站数据/数据
ls
 木鱼水心数据.xlsx  '爬取b站up主数据 (copy).ipynb'   静bi~.xlsx

下面对木鱼水心的数据进行分析

import pandas as pd
df = pd.read_excel('木鱼水心数据.xlsx', 'Sheet1')
data = df[['aid', '视频标题', '上传时间', '弹幕数量', '播放量', '评论量']]
data
aid视频标题上传时间弹幕数量播放量评论量
0258309004鲁智深武松再上线!哥哥我想上梁山!《水浒传》P2916573716872652411447283781
1813123558画风突变!宋江:用魔法打败魔法!《水浒传》P2816567705681966214929663753
2427790000水浒最具争议剧情之一!《水浒传》P2716561617404040422590999804
3427516374全员内鬼!史诗级大乱斗之三打祝家庄!《水浒传》P2616555536821862513906294281
4727459148副本开启!梁山最美女将解锁!一只鸡引发的血案!《水浒传》P2516549490052194415685693070
.....................
1182746399【木鱼动画教室@第五期】如何写对话【最终幻想13】1378257965147840995103
1183744150【木鱼动画教室@第四期】怎么拍对话【龙与虎】1378078717214550188136
1184741112【木鱼动画教室@第三期】游戏CG特点【星际争霸2虫群之心】1377914578173887845141
1185741106【木鱼动画教室@第二期】怎么写出感人故事【龙门镖局】1377914442174288059202
1186739057【木鱼动画教室@第一期】插入镜头【FLCL】137779264014602029951646

1187 rows × 6 columns

time = pd.to_datetime(data['上传时间'], unit='s')
danmu = data['弹幕数量']
view = data['播放量']
comment = data['评论量']
danmu.sort_values()
67           0
248          0
1079       102
1108       111
1095       117
         ...  
564      55233
103      58507
127      59823
821     104061
215     166861
Name: 弹幕数量, Length: 1187, dtype: int64
data['视频标题'][821]
'【木鱼微剧场】《三国演义》(全集)'
import matplotlib.pyplot as plt
import numpy as np
plt.title("播放量的情况")
plt.xlabel("日期")
plt.ylabel("数量")
plt.yticks((np.arange(0,40000, 10000)))
#plt.plot(time, danmu, label='弹幕量')
#plt.plot(time, view, 'g', label='播放量')
plt.plot(time, comment, label='评论量')
plt.legend(loc='upper left')
<matplotlib.legend.Legend at 0x7f7005cfea40>

from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType

bar = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    .add_xaxis(time.tolist())
    .add_yaxis('评论', comment.tolist())
    .add_yaxis('播放量', view.tolist())
)

bar.render_notebook()
    <div id="7dc030caa307413885b9d54f78aba1d6" style="width:900px; height:500px;"></div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值