-
-
可以发现B站视频是分片获取的,并且先发起options预请求,在发起get请求获取视频数据,视频和音频文件url路径也有不同,下面定位两个url链接位置
-
通过请求获取携带的参数名定位视频url链接在页面源码中存在的位置
-
对页面发起请求,使用etree封装获取到的页面文档,使用xpath定位字符串位置,再通过json模块将字符串转化为json字符串,获取视频url地址和音频url地址,代码如下
-
def GetBiliVideo(url,session=requests.session()):
res = requests.get(url=url,headers = headers)
html = etree.HTML(res.content)
videoInfo = html.xpath('/html/head/script[3]/text()') # 解析出真实地址存在的位置
# videoJson = json.loads(str(videoInfo[0].split('=')[1]))
videoJson = json.loads(videoInfo[0].split('=',1)[1]) # 切出符合转化要求的字符串并转化为json字符串
videoUrl = videoJson['data']['dash']['video'][0]['baseUrl'] #视频地址
audioUrl = videoJson['data']['dash']['audio'][0]['baseUrl'] # 音频地址
BiliDown(videoUrl,audioUrl) # 调用下载函数
-
-
发起请求,并将获取的数据写成文件,
-
def BiliDown(url1,url2,session = requests.session()):
headers.update({'Referer':url})
session.options(url=url1, headers=headers) # 先用options方法查看服务器资源
res = session.get(url=url1, headers=headers, ) # 然后get获取视频二进制文件
session.options(url=url2, headers=headers) # 音频的
res2 = session.get(url=url2, headers=headers, )
with open(r'E:ESvideoili.mp4', 'wb') as fp: # 存视频
fp.write(res.content)
with open(r'E:ESvideoili1.mp4', 'wb') as fp1: # 存音频
fp1.write(res2.content)
-
-
可以获得视频和音频文件,通过ffmpeg将视频和音频合成
-
def combine_audio(video_file, audiio_file, out_file):
try:
cmd =r'E:ffmpegffmpeg-4.2.2-win64-staticin/ffmpeg -i '+video_file+' -i '+audiio_file+' -acodec copy '+out_file
print(cmd)
subprocess.call(cmd, shell=True) # "Muxing Done
print('done!!!')
return True
except Exception:
return False -
速度有点慢,14分钟音频视频大概花了7分钟来合成.
-
-
整体代码如下,尚未完善,只是做了单个视频爬取
-
import requests
import json
from lxml import etree
import os
import subprocess
url = 'https://www.bilibili.com/video/BV1Mi4y1G7ZH' # 视频页面地址
headers = {
'Referer': 'https://www.bilibili.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36'
}
def GetBiliVideo(url,session=requests.session()):
res = requests.get(url=url,headers = headers)
html = etree.HTML(res.content)
videoInfo = html.xpath('/html/head/script[3]/text()') # 解析出真实地址存在的位置
# videoJson = json.loads(str(videoInfo[0].split('=')[1]))
videoJson = json.loads(videoInfo[0].split('=',1)[1]) # 切出符合转化要求的字符串并转化为json字符串
videoUrl = videoJson['data']['dash']['video'][0]['baseUrl'] #视频地址
audioUrl = videoJson['data']['dash']['audio'][0]['baseUrl'] # 音频地址
BiliDown(videoUrl,audioUrl) # 调用下载函数
def BiliDown(url1,url2,session = requests.session()):
headers.update({'Referer':url})
session.options(url=url1, headers=headers) # 先用options方法查看服务器资源
res = session.get(url=url1, headers=headers, ) # 然后get获取视频二进制文件
session.options(url=url2, headers=headers) # 音频的
res2 = session.get(url=url2, headers=headers, )
with open(r'E:ESvideoili.mp4', 'wb') as fp: # 存视频
fp.write(res.content)
with open(r'E:ESvideoili1.mp4', 'wb') as fp1: # 存音频
fp1.write(res2.content)
# path都需要使用全路径
combine_audio(r'E:ESvideoili.mp4',r'E:ESvideoili1.mp4',r'E:ESvideoili2.mp4')
# 组合音频和视频 (自己加的)
def combine_audio(video_file, audiio_file, out_file):
try:
cmd =r'E:ffmpegffmpeg-4.2.2-win64-staticin/ffmpeg -i '+video_file+' -i '+audiio_file+' -acodec copy '+out_file
print(cmd)
subprocess.call(cmd, shell=True) # "Muxing Done
print('done!!!')
return True
except Exception:
return False
GetBiliVideo(url)
-