1. 程式人生 > 程式設計 >詳解python爬取彈幕與資料分析

詳解python爬取彈幕與資料分析

很不幸的是,由於疫情的關係,原本線下的AWD改成線上CTF了。這就很難受了,畢竟AWD還是要比CTF難一些的,與人鬥現在變成了與主辦方鬥。
雖然無奈歸無奈,但是現在還是得打起精神去面對下一場比賽。這個開始也是線下的,決賽地點在南京,後來是由於疫情的關係也成了線上。
當然,比賽內容還是一如既往的得現學,內容是關於大資料的。
由於我們學校之前並沒有開設過相關培訓,所以也只能自己琢磨了。
好了,廢話先不多說了,正文開始。

一.比賽介紹

大資料總體來說分為三個過程。
第一個過程是搭建hadoop環境。
這個開始我也挺懵的,不過後來看了個教程大概懂了。總的來說,hadoop就是一個整合環境,這個環境裡面包含了很多軟體。

這些軟體的功能各不相同,比如檔案分散式(原諒我也忘了叫啥),大概作用就是假設你電腦有1個g大小,但是一個檔案有10個g,那麼你就可以用這個系統,將檔案割成10份分別儲存。
總的來說,就是為了大資料而服務的一個環境。

第二個過程就是爬取資料。
這個依據比賽的要求而定,我記得初賽的時候是要求爬取一個開源的電商網站,名字好像是SHOPXO。這個有爬蟲的基礎的同學可以去試下。
決賽還沒比,不過好像是要爬取視訊的彈幕。這個要比單純的爬取視訊麻煩一點,因為每個網站對彈幕的演算法不一樣。
一會兒我會寫兩個爬蟲,分別爬取B站和A站的彈幕你們就知道了。

第三個過程就是分析資料。
這個說實話我也不太清楚。分析這一步其實python就可以做,但是貌似又得在那個環境裡做。。。挺懵的,所以這裡就不詳細寫了。

在寫這篇帖子之前,我還寫過一篇關於awd比賽的東西。不過由於其中涉及到很多比較特殊的東西,暫時無法外傳,所以我就先設定成私密的了。
關於大資料其實我和你們一樣是新手,只不過以前因為一些需要剛好學過爬蟲,因此我負責的就是第二塊內容。接下來我也會通篇講一些爬蟲和資料分析的東西。

二.爬蟲

這個可以說是大資料裡面很重要的東西了,因為即使你前面分析做的再好,沒有資料供你分析又有什麼用呢?所以,學好爬蟲。
爬蟲其實是一種代稱,只是功能比較特殊,所以這麼叫。在沒學過爬蟲之前,先想想看,我們正常是如何獲取一些資訊呢?就比如我們想知道周杰倫的歌單都有什麼的時候。
第一步肯定是去百度搜索周杰倫,然後我們就可以在qq音樂之類的音樂網站上看到周杰倫的歌單。爬蟲也得這樣。

它沒有你想象的那麼神奇,肯定是要在某些網站上操作才行。

接著,你就可以一點一點的記錄下來周杰倫的資訊。我們的爬蟲實現的也是這樣的過程,只不過你一秒鐘只能訪問一個頁面,而爬蟲一秒鐘可以訪問幾萬個頁面。

好了,關於爬蟲的更詳細的東西就先不說了,我們不是專門講爬蟲的。csdn上面有很多寫爬蟲的教程,都很詳細。
我們主要的目的是進行實戰。

三.爬取網站彈幕

本來是想以網站視訊資訊作為題目的,但是那個實在是沒啥難度,正好比賽用得到彈幕,乾脆就講講彈幕怎麼爬取吧。

1.A站

A站相對於B站要簡單一點。我們先觀察網頁。比如,這個是我隨便開啟的一個視訊。
現在網站上的這些資料大部分都是動態的,因此我們不能直接用html解析器來解析網頁,得直接爬取xhr裡面的資料。

先按F12抓包。然後我們在搜尋欄中隨便搜尋一條我們的彈幕。

在這裡插入圖片描述

很幸運,只有一個。我們雙擊這個查詢的結果並進行觀察。點到privew,可以發現這裡麵包含了我們所有的彈幕。

在這裡插入圖片描述

因此,這種網站直接爬取就行了。點到headers,我們觀察引數以及請求方式。

在這裡插入圖片描述
在這裡插入圖片描述

ok。這些得到了以後,上指令碼。

import requests
url="https://www.acfun.cn/rest/pc-direct/new-danmaku/poll"
headers={
  "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/86.0.4240.193 Safari/537.36","cookie":""
  #注意,cookie要填你自己的。A站有些特殊,爬取的時候需要加上cookie。
  }
data={
  "videoId":"15779946","lastFetchTime":"0","enableAdvanced":"true"
  }
html=requests.post(url,headers=headers,data=data)
html=html.json()
html=html["added"]
for i in html:
  print(i["body"])

效果如圖。

在這裡插入圖片描述

數量我數了一下,剛好是這個視訊的彈幕數。你們可以新增自己的東西上去,比如增加寫入檔案啥的功能。

2.B站

這個有點特殊了。B站的彈幕是另一種演算法。
B站將彈幕單獨剝離出來到了一個網頁上,需要視訊對應的cid才可以獲得到彈幕對應的碼,然後獲得視訊的彈幕資訊。舉個例子:【嗶哩嗶哩2019拜年祭】

首先,我們要獲取到視訊的視訊號以前是av號,現在是bv號。

在這裡插入圖片描述

然後將這個連結加上你的bv號。這個是嗶哩嗶哩的一個api,可以獲得cid。
https://api.bilibili.com/x/player/pagelist?bvid=BV17t411y7R1&jsonp=jsonp
將連線中的bvid換成bv號。

如圖,我們發現了視訊有4個cid。

在這裡插入圖片描述

接著我們使用下一個api,這樣就可以獲得彈幕了。
https://comment.bilibili.com/76457841.xml
將後面的數字換成剛找到的cid。

結果如圖:

在這裡插入圖片描述

很好。這就是我們手動獲得彈幕的流程,接下來就是用爬蟲做出來就行了。

第一步,將bv轉成av號。其實你可以直接用bv號,但是由於我做這個帖子之前的時候用的是av號找的,所以加了這麼一步。
這一步直接去網上找工具就行了,有很多,就不往程式碼上面加了。

第二部,用剛才給的第二個api獲得cid。我們使用爬蟲即可,將網址構造成規定的格式。
https://www.bilibili.com/widget/getPageList?aid=?
問號換成aid。

第三步,爬取。可以看到我們最終返回的是一個xml檔案,所以用爬蟲裡面的xml解析器解析即可。

別的就不廢話了,直接上程式碼。有啥沒看懂的評論區問。

import requests
from bs4 import BeautifulSoup
import lxml

aid=input("請輸入av號:如果是bv碼請轉換為av號\n")
file_name=input("請輸入儲存檔名:\n")
f=open(file_name,"a",encoding='utf-8')
headers={
  "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/86.0.4240.193 Safari/537.36"
  }
get_cid="https://www.bilibili.com/widget/getPageList?aid="+aid
cid_list=eval(requests.get(get_cid).text)
for cid in cid_list:
  cid=cid["cid"]
  xml="https://comment.bilibili.com/"+str(cid)+".xml"
  html=requests.get(xml,headers=headers)
  html.encoding=html.apparent_encoding
  soup=BeautifulSoup(html.text,"xml").find_all("d")
  for dm in soup:
    f.write(dm.text+"\n")
f.close()

這個是直接將彈幕檔案儲存到本地了,為了方便後續的分析。結果如圖。

在這裡插入圖片描述

一共是九萬多條彈幕。

行了,剩下的就懶得寫了。

四.資料分析

要說分析的話其實這個是很廣的,得依據特定的要求來做。
先說說第一個,高頻詞統計。
程式碼是我copy的,簡單但是好用。
(將上一步的檔案放到和指令碼同一個目錄下)

import jieba.analyse
f =open(r'bilibil週年慶.txt',encoding='utf-8')#開啟檔案
text=f.read() #讀取檔案
text_list=jieba.analyse.extract_tags(text,topK=40)#進行jieba分詞,並且取頻率出現最高的40個詞
text_list=",".join(text_list)#用空格將這些字串連線起來
print(text_list)

如圖,40個出現字數最多的詞彙就被統計出來了。

在這裡插入圖片描述

由於是機器識別,難免不準,所以不要在意這些莫名其妙出現的次。

在說說第二個,情感分析。這個是我猜測可能會用的到的東西。
我們這個可以直接用baiduAPI來做,要比我們自己的寫的好。這個api會將所有的資料進行情感預測,並且返回積極或者消極的概率。
不過你首先得去申請一個百度api的賬號。這個就不說了,百度有教程。
程式碼也是我copy的。首先感謝下原作者,寫的真的很棒。
(原本是要兩個指令碼,我改進了一下,寫成了一個指令碼。這個指令碼僅僅測試了兩個詞,如果想對檔案進行分析,稍微改動一下就行了。)

import re
import requests
import json

# 將text按照lenth長度分為不同的幾段
def cut_text(text,lenth):
  textArr = re.findall('.{' + str(lenth) + '}',text)
  textArr.append(text[(len(textArr) * lenth):])
  return textArr # 返回多段值

def get_emotion(access_token,data): # 情感分析
  # 定義百度API情感分析的token值和URL值
  token = access_token 
  url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify?charset=UTF-8&access_token={}'.format(token)

  # 百度情感分析API的上限是2048位元組,因此判斷文章位元組數小於2048,則直接呼叫
  if (len(data.encode()) < 2048):
    new_each = {
      'text': data # 將文字資料儲存在變數new_each中,data的資料型別為string
    }
    new_each = json.dumps(new_each)
    res = requests.post(url,data=new_each) # 利用URL請求百度情感分析API
    # print("content: ",res.content)
    res_text = res.text # 儲存分析得到的結果,以string格式儲存
    result = res_text.find('items') # 查詢得到的結果中是否有items這一項
    positive = 1
    if (result != -1): # 如果結果不等於-1,則說明存在items這一項
      json_data = json.loads(res.text)
      negative = (json_data['items'][0]['negative_prob']) # 得到消極指數值
      positive = (json_data['items'][0]['positive_prob']) # 得到積極指數值
      print("positive:",positive)
      print("negative:",negative)
      # print(positive)
      if (positive > negative): # 如果積極大於消極,則返回2
        return 2
      elif (positive == negative): # 如果消極等於積極,則返回1
        return 1
      else:
        return 0 # 否則,返回0
    else:
      return 1
  else:
    data = cut_text(data,1500) # 如果文章位元組長度大於1500,則切分
    # print(data)
    sum_positive = 0.0 # 定義積極指數值總合
    sum_negative = 0.0 # 定義消極指數值總和
    for each in data: # 遍歷每一段文字
      # print(each)
      new_each = {
        'text': each # 將文字資料儲存在變數new_each中
      }
      new_each = json.dumps(new_each)
      res = requests.post(url,data=new_each) # 利用URL請求百度情感分析API
      # print("content: ",res.content)
      res_text = res.text # 儲存分析得到的結果,以string格式儲存
      result = res_text.find('items') # 查詢得到的結果中是否有items這一項
      if (result != -1):
        json_data = json.loads(res.text) # 如果結果不等於-1,則說明存在items這一項
        positive = (json_data['items'][0]['positive_prob']) # 得到積極指數值
        negative = (json_data['items'][0]['negative_prob']) # 得到消極指數值
        sum_positive = sum_positive + positive # 積極指數值加和
        sum_negative = sum_negative + negative # 消極指數值加和
        # print(positive)
    print(sum_positive)
    print(sum_negative)
    if (sum_positive > sum_negative): # 如果積極大於消極,則返回2
      return 2
    elif (sum_positive == sum_negative): # 如果消極等於於積極,則返回1
      return 1
    else:
      return 0 # 否則,返回0

def main():
  # client_id 為官網獲取的API Key, client_secret 為官網獲取的Secret Key
  #這兩個我都空出來了,你用你的填上就行了。
  client_id=""
  client_secret=""
  host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+client_id+'&client_secret='+client_secret
  response = requests.get(host)
  list_new=eval(response.text)
  access_token=list_new["access_token"]
  txt1 = "你好優秀"
  txt2 = "難過!"
  print("txt1測試結果:",get_emotion(access_token,txt1))
  print("txt2測試結果:",txt2))

if __name__ == "__main__":
  main()

效果如圖。

在這裡插入圖片描述

剩下的比如折線圖什麼的就不寫了,百度都有。

到此這篇關於詳解python爬取彈幕與資料分析的文章就介紹到這了,更多相關pythonpython爬彈幕資料分析內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!