效果
輸入要爬取的視頻的BV號即可爬取該視頻的彈幕。
過程
基本思路
基本的思路很簡單,還是老步驟:
1、構造爬取的url
2、解析返回的數據
3、使用json或Xpath或正則表達式提取數據
4、保存數據
尋找url地址
第一步
剛開始還是從網頁版中尋找url地址,結果請求很多,找了半天也沒有找到
第二步
於是我們可以訪問一下手機版的頁面,而根據常識,彈幕這種東西一般是通過ajax來請求的,所以我們過濾一下,只看異步請求。
此時請求就變得少了很多,但是依然沒有找到我們需要的彈幕數據,此時才發現我們並沒有點擊播放視頻。
第三步
彈幕是在視頻播放的過程中播放的,理所當然只有當我們播放視頻並且打開彈幕后才會請求彈幕的數據,我們點擊播放。
點擊播放后我們可以發現請求變多了,再次尋找我們發現 168881748.xml
請求的地址便是彈幕數據了。
第四步
到這里我們就想到了,這種地址是怎么請求的呢?不同的視頻請求的地址肯定是不一樣的,應該是js生成的吧!現在我們來搜索一下該文件名``168881748`
很顯然這是構造出來的地址,我們點進去看一下
不出所料是js構成的請求地址,我們可以發現這便是頁面的數據,我們進一步去驗證一下,刷新頁面,查看一下網頁的數據。
果然在該頁面的文檔中我們找到了
現在的思路
現在思路就很清晰了
1、通過視頻url獲取彈幕文件url
2、爬取彈幕文件url
3、提取數據
代碼實現
# coding=utf-8
import requests
from lxml import etree
import re
class BiliSpider:
def __init__(self,BV):
# 構造要爬取的視頻url地址
self.BVurl = "https://m.bilibili.com/video/"+BV
self.headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Mobile Safari/537.36"}
# 彈幕都是在一個url請求中,該url請求在視頻url的js腳本中構造
def getXml_url(self):
# 獲取該視頻網頁的內容
response = requests.get(self.BVurl, headers = self.headers)
html_str = response.content.decode()
# 使用正則找出該彈幕地址
# 格式為:https://comment.bilibili.com/168087953.xml
# 我們分隔出的是地址中的彈幕文件名,即 168087953
getWord_url = re.findall(" '//comment.bilibili.com/'+ (.*) +'.xml',", html_str)
getWord_url = getWord_url[0].replace("+","").replace(" ","")
# 組裝成要請求的xml地址
xml_url = "https://comment.bilibili.com/{}.xml".format(getWord_url)
return xml_url
# Xpath不能解析指明編碼格式的字符串,所以此處我們不解碼,還是二進制文本
def parse_url(self,url):
response = requests.get(url,headers = self.headers)
return response.content
# 彈幕包含在xml中的<d></d>中,取出即可
def get_word_list(self,str):
html = etree.HTML(str)
word_list = html.xpath("//d/text()")
return word_list
def run(self):
# 1.根據BV號獲取彈幕的地址
start_url = self.getXml_url()
# 2.請求並解析數據
xml_str = self.parse_url(start_url)
word_list = self.get_word_list(xml_str)
# 3.打印
for word in word_list:
print(word)
if __name__ == '__main__':
BVName = input("請輸入要爬取的視頻的BV號:")
spider = BiliSpider(BVName)
spider.run()
這里只打印了彈幕,並沒有保存,可以根據自己的需求進行更改!