python爬取bilibili,下载视频

一. 内容简介

python爬取bilibili,下载视频

二. 软件环境

2.1vsCode

2.2Anaconda

version: conda 22.9.0

2.3代码

链接:https://pan.baidu.com/s/1WuXTso_iltLlnrLffi1kYQ?pwd=1234

三.主要流程

3.1 下载单个视频

代码

import requests
import os
from lxml import etree
import redef videoDownload1(url_):# 设置用户代理,cookieheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}# 发送请求,得到响应对象response_ = requests.get(url_, headers=headers_)str_data = response_.text  # 视频主页的html代码,类型是字符串# 使用xpath解析html代码,,得到想要的urlhtml_obj = etree.HTML(str_data)  # 转换格式类型# 获取视频的名称res_ = html_obj.xpath('//title/text()')[0]# 视频名称的获取title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]# 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了title_ = title_.replace('/', '')title_ = title_.replace(' ', '')title_ = title_.replace('&', '')title_ = title_.replace(':', '')# 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]# 纯视频的urlvideo_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 纯音频的urlaudio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 设置跳转字段的headersheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36','Referer': url_}# 获取纯视频的数据response_video = requests.get(video_url, headers=headers_, stream=True)bytes_video = response_video.content# 获取纯音频的数据response_audio = requests.get(audio_url, headers=headers_, stream=True)bytes_audio = response_audio.content# 获取文件大小, 单位为KBvideo_size = int(int(response_video.headers['content-length']) / 1024)audio_size = int(int(response_audio.headers['content-length']) / 1024)# 保存纯视频的文件title_1 = title_ + '!'  # 名称进行修改,避免重名title_1 = title_1.replace(':', '_')with open(f'{title_1}.mp4', 'wb') as f:f.write(bytes_video)# print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')with open(f'{title_1}.mp3', 'wb') as f:f.write(bytes_audio)# print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')# 利用第三方工具ffmpeg 合成视频, 需要执行终端命令ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"# os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')folder_path = f"./video/{title_}"  # 替换为你想要创建的文件夹路径if not os.path.exists(folder_path):os.mkdir(folder_path)# print(f"The folder '{folder_path}' already exists.")command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{title_}/{title_}.mp4 -loglevel quiet'os.system(command)# 显示合成文件的大小print(f'{title_}  下载完成')# 移除纯视频文件,os.remove(f'{title_1}.mp4')# 移除纯音频文件,os.remove(f'{title_1}.mp3')

3.2 下载选集视频

选集视频的播放链接很好找,就是后面的p=几啥的,拼一下就可以拿到整个的播放链接了
代码

import requests
import os
from lxml import etree
import re# 获取网页源码
def getUrls2(url):# 发送请求,得到响应对象# 设置用户代理,cookieheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}response_ = requests.get(url, headers=headers)str_data = response_.text  # 视频主页的html代码,类型是字符串# 使用xpath解析html代码,,得到想要的urlhtml_obj = etree.HTML(str_data)  # 转换格式类型urls = []# 获取了li的数量,lis = html_obj.xpath("//ul[@class='list-box']/li")question_mark_index = url.find('?')# 如果找到了 '?',就截取该位置之前的子串if question_mark_index != -1:cleaned_url = url[:question_mark_index]else:cleaned_url = url# print(cleaned_url)# 拼接apifor i in range(1,len(lis)+1):# print(i)strs = cleaned_url + "?p=" + str(i)urls.append(strs)# print(content)return urls
import requests
import os
from lxml import etree
import redef videoDownload3(url_,i,name):# 设置用户代理,cookieheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}# 发送请求,得到响应对象response_ = requests.get(url_, headers=headers_)str_data = response_.text  # 视频主页的html代码,类型是字符串# 使用xpath解析html代码,,得到想要的urlhtml_obj = etree.HTML(str_data)  # 转换格式类型# 获取视频的名称res_ = html_obj.xpath('//title/text()')[0]# 视频名称的获取title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]fileName = name# 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了title_ = title_.replace('/', '')title_ = title_.replace(' ', '')title_ = title_.replace('&', '')title_ = title_.replace(':', '')title_ = title_.replace('-', '')title_ = title_.replace('—', '')# 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]# 纯视频的urlvideo_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 纯音频的urlaudio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 设置跳转字段的headersheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36','Referer': url_}# 获取纯视频的数据response_video = requests.get(video_url, headers=headers_, stream=True)bytes_video = response_video.content# 获取纯音频的数据response_audio = requests.get(audio_url, headers=headers_, stream=True)bytes_audio = response_audio.content# 获取文件大小, 单位为KBvideo_size = int(int(response_video.headers['content-length']) / 1024)audio_size = int(int(response_audio.headers['content-length']) / 1024)# 保存纯视频的文件title_1 = title_ + '!'  # 名称进行修改,避免重名title_1 = title_1.replace(':', '')with open(f'{title_1}.mp4', 'wb') as f:f.write(bytes_video)# print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')with open(f'{title_1}.mp3', 'wb') as f:f.write(bytes_audio)# print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')# 利用第三方工具ffmpeg 合成视频, 需要执行终端命令ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"# os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')folder_path = f"./video/{fileName}"  # 替换为你想要创建的文件夹路径if not os.path.exists(folder_path):os.mkdir(folder_path)# print(f"The folder '{folder_path}' already exists.")command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{fileName}/{i}.{title_1}.mp4 -loglevel quiet'file_path = f"./video/{fileName}/{i}.{title_}.mp4"if os.path.exists(file_path):passelse:os.system(command)# 显示合成文件的大小print(f'{i}.{title_}  下载完成')# 移除纯视频文件,os.remove(f'{title_1}.mp4')# 移除纯音频文件,os.remove(f'{title_1}.mp3')

3.3 下载合集视频

合集的里面数据的访问api
在这里插入图片描述
合集里面的数据,就是从这个里面拿到播放id,给json中的处理拿出来,拼接视频播放链接
在这里插入图片描述

代码

# 获取网页源码
def getUrls3(url):# 发送请求,得到响应对象# 设置用户代理,cookieheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}# 使用正则表达式提取数字pattern = r'\d+'numbers = re.findall(pattern, url)mid = numbers[0]season_id = numbers[1]page_num = 1url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={page_num}&page_size=30"response = requests.get(url)if response.status_code == 200:json_data = response.json()# print(json_data["data"]["page"]["total"])total = int(json_data["data"]["page"]["total"])page_size = int(json_data["data"]["page"]["page_size"])page = int(total / page_size) + 1name = json_data["data"]["meta"]["name"]# print(total,page)urls = []# for i in range(1,page+1):# print(i) url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={i}&page_size=30"response = requests.get(url)if response.status_code == 200:json_data = response.json()archives = json_data["data"]["archives"]num = 0for j in archives:bvid = archives[num]["bvid"]videoUrl = f"https://www.bilibili.com/video/{bvid}/"num = num + 1urls.append(videoUrl)return urls,name
import requests
import os
from lxml import etree
import redef videoDownload2(url_,i):# 设置用户代理,cookieheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}# 发送请求,得到响应对象response_ = requests.get(url_, headers=headers_)str_data = response_.text  # 视频主页的html代码,类型是字符串# 使用xpath解析html代码,,得到想要的urlhtml_obj = etree.HTML(str_data)  # 转换格式类型# 获取视频的名称res_ = html_obj.xpath('//title/text()')[0]# 视频名称的获取title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]fileName = html_obj.xpath('//h1[@class="video-title"]/text()')[0]# 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了title_ = title_.replace('/', '')title_ = title_.replace(' ', '')title_ = title_.replace('&', '')title_ = title_.replace(':', '')# 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]# 纯视频的urlvideo_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 纯音频的urlaudio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 设置跳转字段的headersheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36','Referer': url_}# 获取纯视频的数据response_video = requests.get(video_url, headers=headers_, stream=True)bytes_video = response_video.content# 获取纯音频的数据response_audio = requests.get(audio_url, headers=headers_, stream=True)bytes_audio = response_audio.content# 获取文件大小, 单位为KBvideo_size = int(int(response_video.headers['content-length']) / 1024)audio_size = int(int(response_audio.headers['content-length']) / 1024)# 保存纯视频的文件title_1 = title_ + '!'  # 名称进行修改,避免重名title_1 = title_1.replace(':', '_')with open(f'{title_1}.mp4', 'wb') as f:f.write(bytes_video)# print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')with open(f'{title_1}.mp3', 'wb') as f:f.write(bytes_audio)# print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')# 利用第三方工具ffmpeg 合成视频, 需要执行终端命令ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"# os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')folder_path = f"./video/{fileName}"  # 替换为你想要创建的文件夹路径if not os.path.exists(folder_path):os.mkdir(folder_path)# print(f"The folder '{folder_path}' already exists.")command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{fileName}/{i}.{title_}.mp4 -loglevel quiet'file_path = f"./video/{fileName}/{i}.{title_}.mp4"if os.path.exists(file_path):passelse:os.system(command)# 显示合成文件的大小print(f'{i}.{title_}  下载完成')# 移除纯视频文件,os.remove(f'{title_1}.mp4')# 移除纯音频文件,os.remove(f'{title_1}.mp3')

3.4 多线程

代码

import concurrent.futures
import requests# 定义一个下载函数
def download_video(URL):url, index, name = URL.split(" ", 2)videoDownload3(url,index,name)def THREAD(URLS):# 创建线程池,指定线程数量max_workers = 10  # 这里设置线程数量,根据需要进行调整with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:# 提交下载任务给线程池处理futures = [executor.submit(download_video, URL) for URL in URLS]# 等待所有任务完成for future in concurrent.futures.as_completed(futures):try:future.result()  # 获取任务的结果(这里不需要结果)except Exception as e:print(f"An error occurred: {e}")

3.5 结果

url_model = "https://space.bilibili.com/471303350/channel/collectiondetail?sid=1278346 3"
value = url_model.split(' ')
url = value[0]
model = value[1]if model == "1":videoDownload1(url)print("下载完成")
if model == "2":# 接口分析# 点进去的话接口# https://www.bilibili.com/video/BV1qW4y1a7fU/?spm_id_from=333.337.search-card.all.click# 点击视频的话就这样# https://www.bilibili.com/video/BV1qW4y1a7fU?p=1# https://www.bilibili.com/video/BV1qW4y1a7fU?p=2&vd_source=de2dcd0f37ff916ec3f8fb83c6366123# 可以发现不同的集的接口格式应该是这样的,p = 几就是第几集# https://www.bilibili.com/video/BV1qW4y1a7fU?p=1# 查看有多少集# 一种是视频选集那块会写有多少个# 获取源码urls = getUrls2(url)i = 1for index,url in enumerate(urls):videoDownload2(url,index)print("下载完成")
if model == "3":# 接口分析# 视频合计每个视频接口没有规律,然后再播放页中网页没有直接的播放链接,所以就用合集页的链接来分析# 网页里面的每个链接都是动态加载的,需要访问json数据获取,也或者用虚拟浏览器那种等页面加载完成后访问(这种以后可能会更新,感觉这个有点麻烦),# 这里是用json数据做的# https://space.bilibili.com/107762251/channel/collectiondetail?sid=877119# https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=107762251&season_id=877119&sort_reverse=false&page_num=1&page_size=30# https://space.bilibili.com/389199842/channel/collectiondetail?sid=1275285# https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=389199842&season_id=1275285&sort_reverse=false&page_num=1&page_size=30# 这是两个接口,前面那个数字是用户,后面那个数字代表的是合集,下载的接口其实是股东urls,name = getUrls3(url)# print(len(urls))for index,url in enumerate(urls):# print(url)videoDownload3(url,index,name)# print(urls)# 多线程# for index,url in enumerate(urls):#     URLS.append(url + " " + str(index) + " " + name)#     THREAD(URLS)

那切里做展示,有些合集下载时候有点bug,还没找到问题,可以下载,但是保存路径有点问题,应该是和命令行冲突了,我就不改了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6 合集视频更新

原来会出现部分合集显示下载成功,但是文件夹里面没有东西,是因为有些合集名字在命令里面没办法执行,因为一些特殊符号什么的,所以把合集名字手动指定一下下载就可以了,然后多线程加上去,代码如下
拿视频链接的

# 获取网页源码
def getUrls3(url):# 发送请求,得到响应对象# 设置用户代理,cookieheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}# 使用正则表达式提取数字pattern = r'\d+'numbers = re.findall(pattern, url)mid = numbers[0]season_id = numbers[1]page_num = 1url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={page_num}&page_size=30"response = requests.get(url)if response.status_code == 200:json_data = response.json()# print(json_data["data"]["page"]["total"])total = int(json_data["data"]["page"]["total"])page_size = int(json_data["data"]["page"]["page_size"])page = int(total / page_size) + 1name = json_data["data"]["meta"]["name"]# print(total,page)urls = []# for i in range(1,page+1):# print(i) url = f"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid={mid}&season_id={season_id}&sort_reverse=false&page_num={i}&page_size=30"response = requests.get(url)if response.status_code == 200:json_data = response.json()archives = json_data["data"]["archives"]num = 0for j in archives:bvid = archives[num]["bvid"]videoUrl = f"https://www.bilibili.com/video/{bvid}/"num = num + 1urls.append(videoUrl)return urls,name

下载视频的

import requests
import os
from lxml import etree
import redef videoDownload3(url_,index,name):# 设置用户代理,cookieheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Cookie': "buvid3=7014DDC0-BF1E-B121-F5A5-F10753C840B423630infoc; i-wanna-go-back=-1; _uuid=49BF2138-1E10F-D5F5-10898-D8311651B53927883infoc; FEED_LIVE_VERSION=V8; DedeUserID=171300042; DedeUserID__ckMd5=c65bec3211413192; CURRENT_FNVAL=4048; rpdid=|(J|)J~m~llk0J'uYm|)~klRl; header_theme_version=CLOSE; hit-new-style-dyn=1; hit-dyn-v2=1; is-2022-channel=1; fingerprint=fe5c7462625770aa2abce449a7c01fd2; buvid_fp_plain=undefined; b_nut=1691207170; b_ut=5; buvid_fp=fe5c7462625770aa2abce449a7c01fd2; LIVE_BUVID=AUTO4016915564967297; buvid4=1AE73807-AEA0-7078-DA57-7F9FE5C3D6F896987-023080912-A0g5nInZwV3VmJJT68FJxw%3D%3D; home_feed_column=5; SESSDATA=fc1266d3%2C1708653865%2C29c08%2A81-i-T9HQrucvpCVcPwSwXl5LmjTyduIzF9veu0KS9i2IwXK_xkcqlt1XQyxJ3sG-9HMSwLwAAKgA; bili_jct=068bc0a79f3fa7aa1a030e478dbf6d4b; sid=5yvjlnfi; browser_resolution=1920-971; bili_ticket=eyJhbGciOiJFUzM4NCIsImtpZCI6ImVjMDIiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2OTMzNjY1MTcsImlhdCI6MTY5MzEwNzMxNywicGx0IjotMX0.I1Yfp8S9UIkU4S0G5vtBJfslPtgY7QLCj1dx9WQpyRmxKpZoA1qB5UYXNW4KBSZFGljMm7F1lbGXSGco7F79JZJ2sZNBvH9QiSVlmipzAJKaucIoFh6s3m1jpqjLp10r; bili_ticket_expires=1693366517; bp_video_offset_171300042=834376858445283367; b_lsid=1021245DB_18A3567E5C2; CURRENT_QUALITY=80; PVID=2"}# 发送请求,得到响应对象response_ = requests.get(url_, headers=headers_)str_data = response_.text  # 视频主页的html代码,类型是字符串# 使用xpath解析html代码,,得到想要的urlhtml_obj = etree.HTML(str_data)  # 转换格式类型# 获取视频的名称res_ = html_obj.xpath('//title/text()')[0]# 视频名称的获取title_ = re.findall(r'(.*?)_哔哩哔哩', res_)[0]# 影响视频合成的特殊字符的处理,目前就遇到过这三个,实际上很有可能不止这三个,遇到了就用同样的方法处理就好了title_ = title_.replace('/', '')title_ = title_.replace(' ', '')title_ = title_.replace('&', '')title_ = title_.replace(':', '')# 使用xpath语法获取数据,取到数据为列表,索引[0]取值取出里面的字符串,即包含视频音频文件的url字符串url_list_str = html_obj.xpath('//script[contains(text(),"window.__playinfo__")]/text()')[0]# 纯视频的urlvideo_url = re.findall(r'"video":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 纯音频的urlaudio_url = re.findall(r'"audio":\[{"id":\d+,"baseUrl":"(.*?)"', url_list_str)[0]# 设置跳转字段的headersheaders_ = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36','Referer': url_}# 获取纯视频的数据response_video = requests.get(video_url, headers=headers_, stream=True)bytes_video = response_video.content# 获取纯音频的数据response_audio = requests.get(audio_url, headers=headers_, stream=True)bytes_audio = response_audio.content# 获取文件大小, 单位为KBvideo_size = int(int(response_video.headers['content-length']) / 1024)audio_size = int(int(response_audio.headers['content-length']) / 1024)# 保存纯视频的文件title_1 = title_ + '!'  # 名称进行修改,避免重名title_1 = title_1.replace(':', '_')with open(f'{title_1}.mp4', 'wb') as f:f.write(bytes_video)# print(f'{title_1}纯视频文件下载完毕...,大小为:{video_size}KB, {int(video_size/1024)}MB')with open(f'{title_1}.mp3', 'wb') as f:f.write(bytes_audio)# print(f'{title_1}纯音频文件下载完毕...,大小为:{audio_size}KB, {int(audio_size/1024)}MB')# 利用第三方工具ffmpeg 合成视频, 需要执行终端命令ffmpeg_path = r".\ffmpeg\bin\ffmpeg.exe"# os.system(f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy .\video\{title_}.mp4 -loglevel quiet')folder_path = f"./video/{name}"  # 替换为你想要创建的文件夹路径if not os.path.exists(folder_path):os.mkdir(folder_path)# print(f"The folder '{folder_path}' already exists.")command = f'{ffmpeg_path} -i {title_1}.mp3 -i {title_1}.mp4 -c copy ./video/{name}/{index}.{title_}.mp4 -loglevel quiet'os.system(command)# 显示合成文件的大小print(f'{title_}  下载完成')# 移除纯视频文件,os.remove(f'{title_1}.mp4')# 移除纯音频文件,os.remove(f'{title_1}.mp3')

多线程

import concurrent.futures
import requests# 定义一个下载函数
def download_video(URL):url, index, name = URL.split(" ", 2)videoDownload3(url,index,name)def THREAD(URLS):# 创建线程池,指定线程数量max_workers = 10  # 这里设置线程数量,根据需要进行调整with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:# 提交下载任务给线程池处理futures = [executor.submit(download_video, URL) for URL in URLS]# 等待所有任务完成for future in concurrent.futures.as_completed(futures):try:future.result()  # 获取任务的结果(这里不需要结果)except Exception as e:print(f"An error occurred: {e}")

执行


url_model = "https://space.bilibili.com/389199842/channel/collectiondetail?sid=1275285 3"
value = url_model.split(' ')
url = value[0]
model = value[1]if model == "1":videoDownload1(url)print("下载完成")
if model == "2":# 接口分析# 点进去的话接口# https://www.bilibili.com/video/BV1qW4y1a7fU/?spm_id_from=333.337.search-card.all.click# 点击视频的话就这样# https://www.bilibili.com/video/BV1qW4y1a7fU?p=1# https://www.bilibili.com/video/BV1qW4y1a7fU?p=2&vd_source=de2dcd0f37ff916ec3f8fb83c6366123# 可以发现不同的集的接口格式应该是这样的,p = 几就是第几集# https://www.bilibili.com/video/BV1qW4y1a7fU?p=1# 查看有多少集# 一种是视频选集那块会写有多少个# 获取源码urls = getUrls2(url)i = 1for index,url in enumerate(urls):videoDownload2(url,index)print("下载完成")
if model == "3":# 接口分析# 视频合计每个视频接口没有规律,然后再播放页中网页没有直接的播放链接,所以就用合集页的链接来分析# 网页里面的每个链接都是动态加载的,需要访问json数据获取,也或者用虚拟浏览器那种等页面加载完成后访问(这种以后可能会更新,感觉这个有点麻烦),# 这里是用json数据做的# https://space.bilibili.com/107762251/channel/collectiondetail?sid=877119# https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=107762251&season_id=877119&sort_reverse=false&page_num=1&page_size=30# https://space.bilibili.com/389199842/channel/collectiondetail?sid=1275285# https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=389199842&season_id=1275285&sort_reverse=false&page_num=1&page_size=30# 这是两个接口,前面那个数字是用户,后面那个数字代表的是合集,下载的接口其实是股东urls,name = getUrls3(url)name = "qml项目"URLS = []# print(len(urls))for index,url in enumerate(urls):# print(url)URLS.append(url + " " + str(index+1) + " " + name)THREAD(URLS)print("全部下载完成!!!")# print(urls)# for index,url in enumerate(urls):#     URLS.append(url + " " + str(index) + " " + name)#     THREAD(URLS)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

四.参考

http://t.csdn.cn/6Pt7v 想下载B站视频却不知如何下手?一文教你爬B站!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/61092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优思学院|六西格玛中的概率分布有哪些?

为什么概率分布重要? 概率分布是统计学中一个重要的概念,它帮助我们理解随机变量的分布情况以及与之相关的概率。在面对具体问题时,了解概率分布可以帮助我们选择适当的检验或分析策略,以解决问题并做出合理的决策。 常见的概率…

Redis问题集合(三)在Redis容器里设置键值对

前言 前提是已经拉取了Redis镜像并创建了对应的容器做个记录,方便后续查看 步骤 查看Redis容器的ID:docker ps -a 进入容器:docker exec -it 容器ID /bin/bash进入redis命令行:redis-cli输入密码:auth 配置密码 查看…

Apipost:为什么是开发者首选的API调试工具

文章目录 前言正文接口调试接口公共参数、环境全局参数的使用快速生成并导出接口文档研发协作接口压测和自动化测试结论 前言 Apipost是一款支持 RESTful API、SOAP API、GraphQL API等多种API类型,支持 HTTPS、WebSocket、gRPC多种通信协议的API调试工具。除此之外…

【使用DataEase数据可视化分析工具访问cpolar】

DataEase 是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务的改进与优化。是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务的改进与优化。 在本地搭建后,借助cpolar 内…

Java-泛型

文章目录 Java泛型什么是泛型?在哪里使用泛型?设计出泛型的好处是什么?动手设计一个泛型泛型的限定符泛型擦除泛型的通配符 结论 Java泛型 什么是泛型? Java泛型是一种编程技术,它允许在编译期间指定使用的数据类型。…

E9—TEMAC IP实现千兆网口UDP传输2023-08-28

1.关于IP收费的问题 Tri Mode Ethernet MAC是收费IP,打开IP后,当左下角显示Bought IP license available则IP可用。 2.功能说明 应用搭建的场景是,上位机发送数据,首先发起arp请求,随后下位机给出arp应答响应&#…

说说我最近筛简历和面试的感受。。

大家好,我是鱼皮。 都说现在行情不好、找工作难,但招人又谈何容易?! 最近我们公司在招开发,实习社招都有。我收到的简历很多,但认真投递的、符合要求的却寥寥无几,而且都是我自己看简历、选人…

【Unity-Cinemachine相机】虚拟相机(Virtual Camera)的本质与基本属性

我们可以在游戏进行时修改各个属性,但在概念上,最好将Virtual Camera 当作一种相机行为的“配置文件”,而不是一个组件。 我们的相机有几种行为就为它准备几种虚拟相机,比如角色移动就为它第三人称相机,瞄准就准备一个…

驾驶员监控系统DMS系统功能规范

概述 文档范围 该文档阐述了DMS系统的功能场景、系统组成、接口需求等。 目的 该功能规范为DMS系统及周边件的开发提供参考。 缩写与定义 英文缩写 英文全称 中文描述 DMS: Driver Monitoring System 驾驶员监控系统 MPU: Micro Processor Unit 微处理器单元 IECU: …

软技能的重要性:在面试中展示团队合作与沟通能力

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

【ctf题目系列】ctfwiki pwn类型

categories: ctf ret2shellcode [rootningan ret2shellcode]# ./ret2shellcode No system for you this time !!! 123 bye bye ~[rootningan ret2shellcode]#checksec检查 [rootningan ret2shellcode]# checksec ret2shellcode [!] Could not populate PLT: future feature …

CNN 02(CNN原理)

一、卷积神经网络(CNN)原理 1.1 卷积神经网络的组成 定义 卷积神经网络由一个或多个卷积层、池化层以及全连接层等组成。与其他深度学习结构相比,卷积神经网络在图像等方面能够给出更好的结果。这一模型也可以使用反向传播算法进行训练。相比较其他浅层或深度神经…

Mysql-InnoDB记录结构

一、InnoDB简介 InnoDB 采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的1…

编程题四大算法思想(二)——回溯法:N皇后问题、子集和问题、地图填色问题、迷宫问题

文章目录 回溯法迷宫游戏 N皇后问题基本概念解空间4后问题的解空间 可行解和最优解回溯法回溯法术语回溯法的关键问题回溯法的基本思想4后问题的约束条件n后问题生成问题状态的基本方法 子集和问题一个朴素的求解方法回溯回溯法的剪枝技术 地图填色问题 回溯法 迷宫游戏 深度优…

使用 Python编程: 下载 YouTube 音频的桌面应用程序

最近我开发了一个使用 Python 编写的桌面应用程序,可以方便地下载 YouTube 音频。该应用程序使用了 wxPython、yt_dlp 和 tqdm 库,提供了一个简单直观的用户界面,并具备高效的下载功能。 C:\pythoncode\new\youtube-dl-audio.py 程序介绍 …

为了他的鸟,做件很叛逆很酷的事儿

有种鸟儿,叫隐鹮(Geronticus eremita),大小如鹅,头部光秃,嘴巴巨大,一个字,丑。可是,它还有一个特点,面临濒危。 为了能在欧洲冬季存活,这种鸟儿需…

webassembly003 ggml GGML Tensor Library part-2 官方使用说明

https://github.com/ggerganov/whisper.cpp/tree/1.0.3 GGML Tensor Library 官方有一个函数使用说明,但是从初始版本就没修改过 : https://github1s.com/ggerganov/ggml/blob/master/include/ggml/ggml.h#L3-L173 This documentation is still a work in progres…

安达发|富士康科技集团利用自动排程APS软件打造智慧工厂

富士康科技集团作为全球领先的3C产品研发制造企业,近年来积极布局智能制造领域,通过引入先进的自动化排程系统(APS),成功打造了智慧工厂,提高了生产质量与效率,降低了生产成本。 富士康集团自2019年下半年提出在观澜厂区建立数字可…

C++ list模拟实现

list模拟实现代码&#xff1a; namespace djx {template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x T()):_data(x),_prev(nullptr),_next(nullptr){}};template<class T,class Ref,class Pt…

Linux 云服务器挂载数据盘

1、检查linux服务器磁盘情况 df -h 可以看到无磁盘挂载信息。 2、查看待挂载磁盘信息 fdisk -l 可以看到40G系统盘、50G数据盘&#xff08;盘符&#xff1a;/dev/vdb&#xff09; 3、对数据盘分区 fdisk /dev/vdb 根据提示&#xff0c;依次输入“n”&#xff0c;“p”“1…