B站分片视频爬取

  1. 先确定视频的获取方式,通过浏览器抓包

  2. 可以发现B站视频是分片获取的,并且先发起options预请求,在发起get请求获取视频数据,视频和音频文件url路径也有不同,下面定位两个url链接位置

  3. 通过请求获取携带的参数名定位视频url链接在页面源码中存在的位置

  4. 对页面发起请求,使用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) # 调用下载函数
  5. 发起请求,并将获取的数据写成文件,

    •  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:\ES\video\bili.mp4', 'wb') as fp: # 存视频
              fp.write(res.content)
       
          with open(r'E:\ES\video\bili1.mp4', 'wb') as fp1: # 存音频
              fp1.write(res2.content)                
       
  6. 可以获得视频和音频文件,通过ffmpeg将视频和音频合成

    •  def combine_audio(video_file, audiio_file, out_file):
          try:
              cmd =r'E:\ffmpeg\ffmpeg-4.2.2-win64-static\bin/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分钟来合成.

  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:\ES\video\bili.mp4', 'wb') as fp: # 存视频
              fp.write(res.content)
       
          with open(r'E:\ES\video\bili1.mp4', 'wb') as fp1: # 存音频
              fp1.write(res2.content)
       
          # path都需要使用全路径
          combine_audio(r'E:\ES\video\bili.mp4',r'E:\ES\video\bili1.mp4',r'E:\ES\video\bili2.mp4')
       
       # 组合音频和视频 (自己加的)
       def combine_audio(video_file, audiio_file, out_file):
          try:
              cmd =r'E:\ffmpeg\ffmpeg-4.2.2-win64-static\bin/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)

猜你喜欢

转载自www.cnblogs.com/W-Y-C/p/13406392.html