video_bvid:
import os
import requests
import json
import re
from bs4 import BeautifulSoup
import subprocess
# from detail_video import video_bvid# video_bvid 是一個從外部得到的單個視頻ID
video_bvid = 'BV1cx421Q7ve'class BilibiliVideoAudio:def __init__(self, bvid):"""初始化方法,接收一個bvid作為視頻的唯一標識符。"""self.bvid = bvid# 設置請求頭,用于模擬瀏覽器訪問Bilibili網站self.headers = {"referer": "https://search.bilibili.com/all?keyword=%E4%B8%BB%E6%92%AD%E8%AF%B4%E8%81%94%E6%92%AD&from_source=webtop_search&spm_id_from=333.1007&search_source=5&page=4&o=90","origin": "https://search.bilibili.com",'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0','Accept-Encoding': 'gzip, deflate, br'}def get_video_audio(self):"""獲取視頻和音頻的鏈接以及視頻標題。"""# 構造視頻鏈接并發送請求獲取頁面內容url = f'https://www.bilibili.com/video/{self.bvid}/?spm_id_from=333.337.search-card.all.click&vd_source=14378ecd144bed421affe1fe0ddd8981'content = requests.get(url, headers=self.headers).content.decode('utf-8')# 使用BeautifulSoup解析HTML內容soup = BeautifulSoup(content, 'html.parser')# 獲取視頻標題meta_tag = soup.head.find('meta', attrs={'name': 'title'})title = meta_tag['content']# 獲取視頻和音頻鏈接的正則表達式pattern = r'window\.__playinfo__=({.*?})\s*</script>'# 提取并解析JSON數據json_data = re.findall(pattern, content)[0]data = json.loads(json_data)# 提取視頻和音頻的基礎URLvideo_url = data['data']['dash']['video'][0]['base_url']audio_url = data['data']['dash']['audio'][0]['base_url']# 返回包含標題、視頻URL和音頻URL的字典return {'title': title,'video_url': video_url,'audio_url': audio_url}def download_video_audio(self, url, filename):"""下載視頻或音頻文件。"""# 對文件名進行清理,去除不合規字符filename = self.sanitize_filename(filename)try:# 發送請求下載文件內容resp = requests.get(url, headers=self.headers).content# 構造下載路徑download_path = os.path.join('D:\\video', filename)# 將文件內容寫入到指定路徑with open(download_path, mode='wb') as file:file.write(resp)# 打印下載完成信息print("{:*^30}".format(f"下載完成:{filename}"))except Exception as e:# 打印異常信息print(e)def sanitize_filename(self, filename):"""清理文件名中的不合規字符。"""# 定義不合規字符的正則表達式invalid_chars_regex = r'[\"*<>?\\|/:,]'# 替換不合規字符為空格sanitized_filename = re.sub(invalid_chars_regex, ' ', filename)return sanitized_filenamedef merge_video_audio(self, video_path, audio_path, output_path):"""使用ffmpeg來合并視頻和音頻。"""try:# 構造ffmpeg命令行參數command = ['ffmpeg','-y', # 覆蓋輸出文件如果它已經存在'-i', video_path, # 輸入視頻路徑'-i', audio_path, # 輸入音頻路徑'-c', 'copy', # 復制原始數據,不進行轉碼output_path # 輸出視頻路徑]# 執行ffmpeg命令subprocess.run(command, check=True)# 打印合并完成信息print(f"視頻和音頻合并完成:{output_path}")except subprocess.CalledProcessError as e:# 打印合并失敗信息print(f"合并失敗: {e}")def main():try:# 只處理一個 bvid(Bilibili 視頻的唯一標識符)bilibili = BilibiliVideoAudio(video_bvid) # 創建一個Bilibili視頻音頻處理對象,傳入視頻bvidvideo_audio_info = bilibili.get_video_audio() # 獲取視頻和音頻的信息# 從返回的信息中提取標題、視頻URL和音頻URLtitle = video_audio_info['title']video_url = video_audio_info['video_url']audio_url = video_audio_info['audio_url']# 定義處理后的視頻存放路徑processed_videos_path = 'D:\\processed_videos'# 如果該路徑不存在,則創建該路徑if not os.path.exists(processed_videos_path):os.makedirs(processed_videos_path)# 構造視頻文件名、音頻文件名和輸出文件名video_filename = f"{title}.mp4"audio_filename = f"{title}.mp3"output_filename = f"{title} - combined.mp4"# 構造視頻文件、音頻文件和輸出文件的完整路徑video_file_path = os.path.join('D:\\video', video_filename)audio_file_path = os.path.join('D:\\video', audio_filename)output_file_path = os.path.join(processed_videos_path, output_filename)# 下載視頻和音頻到指定位置bilibili.download_video_audio(video_url, video_filename) # 下載視頻bilibili.download_video_audio(audio_url, audio_filename) # 下載音頻# 合并下載的視頻和音頻文件到指定輸出路徑bilibili.merge_video_audio(video_file_path, audio_file_path, output_file_path)# 可選:合并后刪除單獨的視頻和音頻文件# os.remove(video_file_path)# os.remove(audio_file_path)except Exception as ex:# 捕獲并打印處理視頻/音頻時發生的異常print(f"處理視頻/音頻 {video_bvid} 失敗: {ex}")main()