B站作為近兩年,二次元流行文化的執(zhí)大旗者,其網(wǎng)站上視頻信息已超過2000W(截止2018-04-10)。到目前為止,B站更多的成為了多元化文化的載體,其年輕活力的氛圍,在各個視頻網(wǎng)站或者論壇都不曾能看到的。故產(chǎn)生興趣爬取視頻信息,看是否可以有所挖掘。
感謝@雄哥和@遜哥的幫助才得以完成這篇文章,不然,還不知怎么應(yīng)對IP限制。
項目地址:https://github.com/UranusLee/bilibili_spider
爬蟲爬取數(shù)據(jù)
1.爬蟲
通過chrome可以看出來B站視頻統(tǒng)計信息是通過js加載,打開開發(fā)者工具可以到stat?aid=31的json文件。
再分析json文件的加載方式,基本可以得到所需要的headers參數(shù)。
因為之前一直都在爬取豆瓣、知乎、拉勾這些有特殊headers的網(wǎng)站,所以,為了省事,還是全部headers都加上。
編寫代碼
import requests
import time
import pymysql
import random
from multiprocessing import Pool
#通過pymysql鏈接mysql
conn = pymysql.connect(host = '127.0.0.1' , port = 3306 , user = 'root' , passwd = '921522' , db = 'practice')
cur = conn.cursor()
result = []
video_list = []
#加載User_Agent函數(shù)
def LoadUserAgent(uafile):
uas = []
with open(uafile,'rb') as uaf:
for ua in uaf.readlines():
if ua:
uas.append(ua.strip()[1:-1])
random.shuffle(uas)
return uas
#加載user_agents.txt文件
uas = LoadUserAgent("user_agents.txt")
def getHtmlInfo(url):
#隨機選擇user_agent
ua = random.choice(uas)
#加載headers
headers = {
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7',
'Connection': 'keep-alive',
'Host': 'api.bilibili.com',
'Origin': 'https://www.bilibili.com',
# 'Referer': 'https://www.bilibili.com/video/' + str(i) + '?spm_id_from=333.338.recommend_report.3',
'User-Agent': ua
}
# 通過requests.get來請求數(shù)據(jù),再通過json()解析
response = requests.get(url, headers=headers, timeout=6).json()
try:
data = response['data']
video = (
data['aid'], data['view'], data['danmaku'],
data['reply'], data['favorite'], data['coin'], data['share'])
video_list.append(video)
print(video_list)
save_db()
# time.sleep(0.4)
except:
print('-----')
# 將數(shù)據(jù)保存至mysql
def save_db():
global video_list, cur, conn
sql = "insert into bili_video values(%s, %s, %s, %s, %s, %s, %s);"
for row in video_list:
try:
# print(row)
cur.execute(sql, row)
except:
conn.rollback()
conn.commit()
video_list = []
if __name__ == '__main__':
for i in range(10, 2000):
pool = Pool(10)
begin = (i-1)*10000
urls = ['https://api.bilibili.com/x/web-interface/archive/stat?aid={}'.format(j) for j in range(begin, begin+10000)]
try:
pool.map(getHtmlInfo, urls)
except:
print("錯誤")
pool.close()
pool.join()
time.sleep(0.2)
pool = Pool(10)
pool.map(getHtmlInfo, urls)
conn.close()
進行爬取的時候,發(fā)生了一點問題,通過不斷測試,基本可以斷定B站有IP訪問限制,基本上是1分鐘150次以下不會封IP,封閉IP一次為5分鐘,所以考慮用代理IP,拿著買好的穩(wěn)定的IP,刻不容緩的加入進來。
#加載代理IP函數(shù)
def LoadProxies(ipfile):
ips = []
with open(ipfile,'r') as ipf:
for ip in ipf.readlines():
if ip:
isf.append(ua.strip())
#隨機打亂列表
random.shuffle(ips)
return ips
#加載proxies.txt文件
ips = LoadProxies("proxies.txt")
def getHtmlInfo(url):
#隨機選擇user_agent
ua = random.choice(uas)
ip = random.choice(ips)
#加載headers
headers = {
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7',
'Connection': 'keep-alive',
'Host': 'api.bilibili.com',
'Origin': 'https://www.bilibili.com',
# 'Referer': 'https://www.bilibili.com/video/' + str(i) + '?spm_id_from=333.338.recommend_report.3',
'User-Agent': ua
}
# 通過requests.get來請求數(shù)據(jù),再通過json()解析
response = requests.get(url, headers=headers, timeout=6,proxies={'https':'https://'+ip}).json()
try:
data = response['data']
video = (
data['aid'], data['view'], data['danmaku'],
data['reply'], data['favorite'], data['coin'], data['share'])
video_list.append(video)
print(video_list)
save_db()
# time.sleep(0.4)
except:
print('-----')
總共爬取下來710多W條數(shù)據(jù),用了三四天的時間,期間網(wǎng)絡(luò)斷掉,或者IP地址停用,一直耽擱,之所以不準(zhǔn)備繼續(xù)下去是因為數(shù)據(jù)還準(zhǔn)備做一個B站每年數(shù)據(jù)分析,所以選用了aid=11883351這條數(shù)據(jù)作為截止可以比較好的對應(yīng)上每年7月初的一個數(shù)據(jù)對比分析
2.讀取數(shù)據(jù)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
filename = 'bili_video.csv'
data = pd.read_csv(filename)
發(fā)現(xiàn)有播放數(shù)為-1的值,總共占數(shù)據(jù)總量的2%,故而刪除。
data = data.drop(data[data.view == -1].index,axis = 0)
3.統(tǒng)計分析
data.describe()
可以看出基本上播放量,彈幕,評論回復(fù),收藏,硬幣,分享基本就是長尾數(shù)據(jù),有大量的小數(shù)值的數(shù)據(jù),但是整體的平均值受極值的影響較大。相比較而言view播放量更加有研究性。
4.分析報告
1.播放量占比分析
總共分為<500,500-1000,1000-5000,5000-20000,>20000。
播放量整體還是大量的淹沒視頻,播放量小于500的達到了整體視頻的48.8%,而播放量20000以上的只占到5.4%,按照“二八原則”,視頻達到3338以上的播放量即達到B站視頻實際效用的界限。
2.分年份分析B站視頻增長速度
以每年7月份為周期分析
通過aid可以查到所有爬下的數(shù)據(jù)所屬的時間,再按照概率分析大概的時間就可以得出每一年7月份的視頻量。
整體的視頻數(shù)量增長速度實際上是大致按照每年翻倍的速度來增長,整體增長曲線拋開10-11年,整體增長平和。
2010-2011年之間,必定是發(fā)生了事才會導(dǎo)致視頻量突增,才會導(dǎo)致視頻總量增長率超過800%。通過查詢,基本確實如之前所假設(shè)一樣,10年因為Ac fun(A站)確實發(fā)生了嚴(yán)重的幾次彈幕沖突,A站關(guān)閉了彈幕系統(tǒng),加上很多人打出“ACG滾出ac”的標(biāo)語,大量的A站up主轉(zhuǎn)移至B站,開始了B站的逆襲。
14年一年視頻增長率唯一一次跌至94%,是因為14年動畫版權(quán)問題,禁止了私自上傳動畫,視頻量比預(yù)期下跌了大概8W左右。今年更加夸張的是2018年還沒有到07月份,視頻總量已經(jīng)達到2200W左右。
3.參與率分析用戶活躍度
彈幕成本是最低的,大概平均27.8人次觀看,就會出現(xiàn)一次彈幕(包括非會員的觀看次數(shù),但是無法發(fā)彈幕,提高了彈幕成本),分享成本不僅僅是會員,非會員沒有登陸也可以分享,這確實42.58人次的成本僅僅高于彈幕成本,說明B站整體視頻風(fēng)格更加多元化。121.58的投幣成本受限于B站的投幣系統(tǒng),B幣少,并且獲得有難度,導(dǎo)致投幣成本遠高于其他幾項。
4.投幣分析
B站投幣有“不牛不投,不服不投”的潛性規(guī)則,往往一個視頻的投幣量可以反應(yīng)視頻的質(zhì)量和B站的流行趨勢。
排名第一的是 【嗶哩嗶哩2017拜年祭】,94.1W投幣
排名第二的是 【古箏】千本櫻——你可見過如此兇殘的練習(xí)曲,79.6W投幣
排名第三的是【嗶哩嗶哩2016拜年祭】,77.2W投幣
然后是敖廠長的兩連擊
【敖廠長】讓你耳朵懷孕的FC游戲,74.6W投幣
【敖廠長】打臉!魂斗羅水下八關(guān)存在,73.0W投幣
其實可以看出前三名中,兩次拜年祭以及用戶群體的自發(fā)投幣,整個拜年祭已經(jīng)成為B站文化的一部分,是每年最核心的一部分。當(dāng)然也不缺乏敖廠長這種良心up主,每一次對于過往游戲的解疑和介紹,還有那無所不能的哥們,宅男但不失真心,牛逼但非常人親。
文化的多元化才是整個B站撐起一片天的本質(zhì)原因,我曾經(jīng)在B站中過《極樂凈土》的毒,看過外國人在中國成了網(wǎng)紅,聽過古箏彈奏魂斗羅、彈奏日本電音。這是一個大熔爐,每個人都可以找到自己喜歡的東西,我突然想起了廣告模塊的一個高分視頻,彈幕量只有300,但是播放量有2000多萬次,我不知道是B站運營人員清空了一部分的彈幕和評論,但是一個廣告在B站,在這個無數(shù)個平時看都不看廣告的年輕人,能夠看上2000多萬次,幾乎人均一次。我才覺得我真正的知道。
這個時代的年輕人是最沉得住氣的,心里再急,也不停的想活出自己想要的樣子,背著裝著自己的背包、還不停的說找不到自己。
----------------------------------------------------分割線-------------------------------------------
數(shù)據(jù)分析的部分有點意猶未盡,今天實在是困了,今天稍晚或者明天會繼續(xù)對于B站各個模塊繼續(xù)進行深挖,包括彈幕的語義分析、通過彈幕揣摩劇情、哪種視頻可以火、up主的影響力、視頻質(zhì)量建模等。