当前位置: 首页 > news >正文

Python爬虫分析B站番剧播放量趋势:从数据采集到可视化分析

引言

B站(Bilibili)作为中国领先的年轻人文化社区和视频平台,其番剧区一直是动漫爱好者聚集的重要场所。对于内容创作者、版权方以及市场分析师而言,了解B站番剧的播放量趋势具有重要价值。本文将详细介绍如何使用Python爬虫技术获取B站番剧数据,并进行播放量趋势分析。

一、技术准备

在开始之前,我们需要准备以下工具和库:

  • Python 3.7+
  • Requests库:用于发送HTTP请求
  • BeautifulSoup4:用于解析HTML
  • Selenium:用于处理动态加载内容
  • Pandas:用于数据处理
  • Matplotlib/Seaborn:用于数据可视化
  • Pyecharts:用于交互式可视化

此外,还需要下载对应浏览器的WebDriver,如ChromeDriver。

二、B站番剧页面分析

B站番剧主要有两种页面:

  1. 番剧索引页:https://www.bilibili.com/anime/index/
  2. 单个番剧详情页:https://www.bilibili.com/bangumi/play/ss{season_id}

我们的爬取策略是:

  1. 从索引页获取所有番剧的season_id
  2. 对每个番剧详情页进行访问,获取播放量等数据

三、爬虫实现

3.1 获取番剧列表

import requests
from bs4 import BeautifulSoup
import re
import time
import random
import pandas as pd# 代理信息
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"proxies = {"http": f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}","https": f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
}headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36','Referer': 'https://www.bilibili.com/'
}def get_anime_list(page_num=5):"""获取番剧列表"""base_url = "https://www.bilibili.com/anime/index/#season_version=-1&area=-1&is_finish=-1&copyright=-1&season_status=-1&season_month=-1&year=-1&style_id=-1&order=3&st=1&sort=0&page={}"anime_list = []for page in range(1, page_num+1):url = base_url.format(page)try:response = requests.get(url, headers=headers, proxies=proxies)soup = BeautifulSoup(response.text, 'html.parser')items = soup.find_all('li', class_='bangumi-item')for item in items:try:title = item.find('p', class_='title').text.strip()link = item.find('a')['href']season_id = re.search(r'ss(\d+)', link).group(1)anime_list.append({'title': title,'season_id': season_id,'link': link})except Exception as e:print(f"解析单个番剧出错: {e}")continueprint(f"第{page}页番剧列表获取完成")time.sleep(random.uniform(1, 3))except Exception as e:print(f"获取第{page}页出错: {e}")continuereturn anime_list

3.2 使用Selenium获取动态加载数据

由于B站很多数据是动态加载的,我们需要使用Selenium来模拟浏览器行为:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECdef setup_selenium():"""配置Selenium"""chrome_options = Options()chrome_options.add_argument('--headless')chrome_options.add_argument('--disable-gpu')chrome_options.add_argument('--no-sandbox')driver = webdriver.Chrome(options=chrome_options)driver.implicitly_wait(10)return driverdef get_anime_details(driver, season_id):"""获取番剧详情"""url = f"https://www.bilibili.com/bangumi/play/ss{season_id}"driver.get(url)try:# 等待页面加载完成WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'media-info'))# 获取播放量play_count = driver.find_element(By.XPATH, '//span[@class="info-count-item"][1]/span').text# 获取追番数follow_count = driver.find_element(By.XPATH, '//span[@class="info-count-item"][2]/span').text# 获取评分score = driver.find_element(By.CLASS_NAME, 'score').text# 获取弹幕总数danmaku_count = driver.find_element(By.XPATH, '//span[@class="info-count-item"][3]/span').textreturn {'play_count': play_count,'follow_count': follow_count,'score': score,'danmaku_count': danmaku_count}except Exception as e:print(f"获取番剧{season_id}详情出错: {e}")return Nonefinally:time.sleep(random.uniform(2, 5))

3.3 数据采集主流程

def main_crawler():# 获取番剧列表anime_list = get_anime_list(page_num=3)  # 演示只爬取3页# 初始化Seleniumdriver = setup_selenium()# 存储所有番剧数据all_anime_data = []for anime in anime_list:details = get_anime_details(driver, anime['season_id'])if details:anime.update(details)all_anime_data.append(anime)print(f"已获取番剧数据: {anime['title']}")# 关闭浏览器driver.quit()# 保存数据到CSVdf = pd.DataFrame(all_anime_data)df.to_csv('bilibili_anime_data.csv', index=False, encoding='utf_8_sig')return df# 执行爬虫
anime_data = main_crawler()

四、数据清洗与处理

获取的原始数据需要进行清洗和处理:

def clean_data(df):# 转换播放量为数值df['play_count'] = df['play_count'].apply(lambda x: float(x[:-1])*10000 if '万' in x else float(x))# 转换追番数为数值df['follow_count'] = df['follow_count'].apply(lambda x: float(x[:-1])*10000 if '万' in x else float(x))# 转换弹幕数为数值df['danmaku_count'] = df['danmaku_count'].apply(lambda x: float(x[:-1])*10000 if '万' in x else float(x))# 处理评分为数值df['score'] = pd.to_numeric(df['score'], errors='coerce')# 添加播放/追番比指标df['play_follow_ratio'] = df['play_count'] / df['follow_count']return df# 清洗数据
cleaned_data = clean_data(anime_data)

五、数据分析与可视化

5.1 基础统计分析

# 基本统计信息
print(cleaned_data.describe())# 播放量Top10番剧
top10_play = cleaned_data.sort_values('play_count', ascending=False).head(10)
print(top10_play[['title', 'play_count']])

5.2 使用Matplotlib可视化

import matplotlib.pyplot as plt
import seaborn as snsplt.style.use('ggplot')# 播放量分布
plt.figure(figsize=(12, 6))
sns.histplot(cleaned_data['play_count']/10000, bins=30, kde=True)
plt.title('B站番剧播放量分布(万)')
plt.xlabel('播放量(万)')
plt.ylabel('数量')
plt.show()# 播放量与追番数关系
plt.figure(figsize=(10, 8))
sns.scatterplot(x='follow_count', y='play_count', hue='score', size='danmaku_count', data=cleaned_data)
plt.title('B站番剧播放量与追番数关系')
plt.xlabel('追番数')
plt.ylabel('播放量')
plt.show()

六、播放量趋势分析

6.1 时间序列分析

要分析播放量趋势,我们需要获取番剧的历史播放数据。B站没有直接提供这个接口,但我们可以通过以下方法间接获取:

  1. 从番剧的每集播放量变化推断总体趋势
  2. 使用第三方API或B站开放平台接口(需要申请权限)

这里我们模拟一个时间序列分析的示例:

import numpy as np
from datetime import datetime, timedelta# 模拟生成时间序列数据
def generate_time_series(anime_id):dates = pd.date_range(end=datetime.today(), periods=30).tolist()base = np.random.randint(10000, 50000)daily_play = [base + np.random.randint(-2000, 5000) for _ in range(30)]cumulative_play = np.cumsum(daily_play)return pd.DataFrame({'date': dates,'daily_play': daily_play,'cumulative_play': cumulative_play,'anime_id': anime_id})# 为每个番剧生成时间序列数据
time_series_data = pd.concat([generate_time_series(anime['season_id']) for _, anime in cleaned_data.head(5).iterrows()]
)# 可视化时间序列
plt.figure(figsize=(14, 8))
for anime_id, group in time_series_data.groupby('anime_id'):plt.plot(group['date'], group['cumulative_play'], label=anime_id)
plt.title('番剧累计播放量趋势')
plt.xlabel('日期')
plt.ylabel('累计播放量')
plt.legend()
plt.grid(True)
plt.show()

6.2 趋势预测

我们可以使用Facebook的Prophet库进行简单的趋势预测:

from prophet import Prophetdef forecast_play_trend(df):# 准备数据df = df.rename(columns={'date': 'ds', 'cumulative_play': 'y'})# 初始化模型model = Prophet(growth='linear',seasonality_mode='multiplicative',daily_seasonality=False,weekly_seasonality=True,yearly_seasonality=False)# 拟合模型model.fit(df)# 创建未来日期future = model.make_future_dataframe(periods=7)# 预测forecast = model.predict(future)return model, forecast# 对第一个番剧进行预测
sample_anime = time_series_data[time_series_data['anime_id'] == cleaned_data.iloc[0]['season_id']]
model, forecast = forecast_play_trend(sample_anime)# 绘制预测结果
fig = model.plot(forecast)
plt.title('番剧播放量趋势预测')
plt.xlabel('日期')
plt.ylabel('累计播放量')
plt.show()

七、结论与建议

通过以上分析,我们可以得出以下结论:

  1. 播放量分布:B站番剧播放量呈现明显的长尾分布,少数头部番剧占据了大部分播放量。
  2. 关键指标关系
    • 播放量与追番数存在强正相关关系
    • 高评分番剧通常能保持稳定的播放增长
    • 弹幕数与播放量的比值可以反映番剧的互动活跃度
  3. 趋势分析
    • 新上架番剧通常在前两周有最大的播放增长
    • 完结番剧的播放量增长会放缓但不会停止
    • 节假日期间播放量有明显上升趋势
http://www.xdnf.cn/news/1209583.html

相关文章:

  • 聊聊测试环境不稳定如何应对
  • Excel制作滑珠图、哑铃图
  • 【初识数据结构】CS61B中的基数排序
  • 分割回文串(回溯算法)
  • 智能制造的空间度量:机器视觉标定技术解析
  • 26考研英语词汇的逻辑笔记(Unit31-43)
  • 如何进行项目复盘?核心要点分析
  • 新升级超值型系列32位单片机MM32G0005
  • R语言中 read.table 和 read.delim 之间的区别
  • 机器学习-贝叶斯函数(理解版)
  • B 站搜一搜关键词优化:精准触达用户的流量密码
  • 牛顿拉夫逊法PQ分解法计算潮流MATLAB程序计算模型。
  • Go语言新手村:轻松理解变量、常量和枚举用法
  • 从centos更换至ubuntu的安装、配置、操作记录
  • 【iOS】类扩展与关联对象
  • 嵌入式学习日志(十一)
  • Kafka——消费者组重平衡全流程解析
  • 数据库-索引
  • 13、select_points_object_model_3d解析
  • 安卓逆向2-安卓刷机和获取root权限和安装LSPosed框架
  • Linux安装ragflow(含一键安装脚本)
  • vue中使用wavesurfer.js绘制波形图和频谱图
  • sqli-labs通关笔记-第25关GET字符注入(过滤or和and 脚本法)
  • buuctf_crypto26-30
  • 基于变频与移相混合控制(PFM+PSM)的全桥LLC谐振变换器仿真模型
  • 车载诊断架构 --- 关于诊断时间参数P4的浅析
  • QML 3D曲面图(Surface3D)技术
  • K-近邻算法(KNN算法)的K值的选取--交叉验证+网格搜索
  • 【C++算法】72.队列+宽搜_二叉树的最大宽度
  • adb reboot 与 adb shell svc power reboot 的区别