基於Python制作B站視頻下載小工具

1. 原理簡介

原理很簡單,就是獲取視頻資源的源地址,然後爬取視頻的二進制內容,再寫入到本地即可。

2. 網頁分析

打開該網頁,然後F12進入開發者模式,接著點開網絡—>全部,因為視頻資源一般比較大,我這裡根據大小進行瞭從大到小的排序,找到瞭第一條這些可能和視頻源地址有關。

然後,我們復制找到的這條裡的url部分不變的部分,回到元素中ctrl+F搜索,找到瞭可能和視頻源地址有關的節點。

果然,我們復制這部分內容,用json在線解析工具發現真的有我們需要的看似視頻文件所在的地址。

然後,我復制這個地址用瀏覽器打開發現提示403瞭。。

不過,沒關系。。我們看接下來的操作!

3. 視頻爬取

在網頁分析部分,我們可以在視頻的B站地址網頁源代碼裡通過各種數據解析的方式來獲取視頻文件的源地址,這裡我采用的是正則表達式。

import requests
import re
import json 

url = 'https://www.bilibili.com/video/BV1BU4y1H7E3'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
    "referer": "https://www.bilibili.com"
    }

resp = requests.get(url, headers=headers)

palyinfo = re.findall(r'<script>window.__playinfo__=(.*?)</script>', resp.text)[0]

palyinfo_data = json.loads(palyinfo)

由於正在表達式獲取的結果是字符串,而實際上它是json(字典),所以這裡需要再引入json庫來進行轉化。

我們再分析數據,可以發現最終視頻文件的信息,直接key-value操作就行瞭。比較有意思的是視頻和音頻文件是分開的,我們需要分別爬取後再合並即可。

# 視頻與音頻文件地址
video_url = json_data['data']['dash']['video'][0]['base_url']
audio_url = json_data['data']['dash']['audio'][0]['base_url']

有朋友可能會發現,base_url貌似有好多個。是的,因為視頻清晰度有很多種嘛。這裡我選取的是第一種超清 4K,大傢可以根據自己需求進行選擇!

當然瞭,我們把視頻存入本地的時候還需要起個名字,這裡隨便找個節點解析出文件名就行瞭。

# 視頻標題
title = re.findall(r'<h1 title="(.*?)" class="video-title">', resp.text)[0]

4. 存入本地

既然我們已經解析獲得瞭視頻的文件地址、音頻地址和文件名,那麼直接就安排下載吧!

不過,我們在網頁分析的時候發現直接打開視頻和音頻文件地址會提示403,那麼因為跳過去的來源不明確導致的,隻需調整請求頭為如下即可:

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
    # 加上referer即可
    "referer": "https://www.bilibili.com"
    }

搞定這些玩意後,我們就開始寫文件寫入本地的函數吧!

# 一般視頻是mp4,音頻是mp3
def down_file(file_url, file_type):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
        "referer": "https://www.bilibili.com"
        }
    resp = requests.get(url = file_url, headers=headers)
    print(resp.status_code)
    
    print(f'文件名稱:{title}')
    # 設置單次寫入數據的塊大小
    chunk_size = 1024
    # 獲取文件大小
    file_size = int(resp.headers['content-length'])
    # 用於記錄已經下載的文件大小
    done_size = 0
    # 將文件大小轉化為MB
    file_size_MB = file_size / 1024 / 1024
    print(f'文件大小:{file_size_MB:0.2f} MB')
    start_time = time.time()
    with open(title + '.' + file_type, mode='wb') as f:
        for chunk in resp.iter_content(chunk_size=chunk_size):
            f.write(chunk)
            done_size += len(chunk)
            print(f'\r下載進度:{done_size/file_size*100:0.2f}%',end='')
    end_time = time.time()
    cost_time = end_time-start_time
    print(f'\n累計耗時:{cost_time:0.2f} 秒')
    print(f'下載速度:{file_size_MB/cost_time:0.2f}M/s')

運行結果:

# 視頻下載
>>>down_file(video_url, 'mp4')
200
文件名稱:【咒術回戰】第20集五條悟帥的有些過分瞭
文件大小:42.10 MB
下載進度:100.00%
累計耗時:5.72 秒
下載速度:7.36M/s
# 音頻下載
>>>down_file(audio_url, 'mp3')
200
文件名稱:【咒術回戰】第20集五條悟帥的有些過分瞭
文件大小:5.13 MB
下載進度:100.00%
累計耗時:0.80 秒
下載速度:6.42M/s

我們在本地可以看到下載成功的視頻文件:

由於視頻和音頻是分開的,所以單獨打開這個視頻是沒有聲音的,我們需要進行合並操作。

合並操作需要用到moviepy庫,關於這個庫我們後續也會介紹它的更多應用,敬請期待~

from moviepy import *
from moviepy.editor import *

video_path = title + '.mp4'
audio_path = title + '.mp3'

# 讀入視頻
video = VideoFileClip(video_path)
# 提取音軌
audio = AudioFileClip(audio_path)
# 將音軌合並到視頻中
video = video.set_audio(audio)
# 輸出
video.write_videofile(f"{title}(含音頻).mp4")

就這樣搞定瞭:

Moviepy - Building video 【咒術回戰】第20集五條悟帥的有些過分瞭(含音頻).mp4.
MoviePy - Writing audio in 【咒術回戰】第20集五條悟帥的有些過分瞭(含音頻)TEMP_MPY_wvf_snd.mp3
MoviePy - Done.                                                       
Moviepy - Writing video 【咒術回戰】第20集五條悟帥的有些過分瞭(含音頻).mp4

Moviepy - Done !
Moviepy - video ready 【咒術回戰】第20集五條悟帥的有些過分瞭(含音頻).mp4

5. GUI工具制作

這個吧,就是用我常用的pysimplegui來操作瞭,比較簡單。

import PySimpleGUI as sg

# 主題設置
sg.theme('SystemDefaultForReal')

# 佈局設置
layout = [[sg.Text('選擇B站視頻地址:',font=("微軟雅黑", 12)),sg.InputText(key='url',size=(50,1),font=("微軟雅黑", 10),enable_events=True) ],
          # [sg.Output(size=(66, 8),font=("微軟雅黑", 10))],  
           [sg.Button('開始下載',font=("微軟雅黑", 10),button_color ='Orange'),
           sg.Button('關閉程序',font=("微軟雅黑", 10),button_color ='red'),]
          ]      

# 創建窗口
window = sg.Window('B站視頻下載工具', layout,font=("微軟雅黑", 12),default_element_size=(50,1))    

# 事件循環
while True:
    event, values = window.read()
    if event in (None, '關閉程序'):
        break
    if event == '開始下載':
        url = values['url']
        print('獲取視頻信息')
        title, video_url, audio_url = get_file_info(url)
        print('下載視頻資源')
        down_file(title, video_url, 'mp4')
        print('下載音頻資源')
        down_file(title, audio_url, 'mp3')   
        print('合並視頻與音頻')
        merge(title)
        print('有音頻視頻處理完成')
window.close()

以上就是基於Python制作B站視頻下載小工具的詳細內容,更多關於Python B站視頻下載的資料請關註WalkonNet其它相關文章!

推薦閱讀: