zoukankan      html  css  js  c++  java
  • 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:ESvideoili.mp4', 'wb') as fp: # 存视频
                fp.write(res.content)
         
            with open(r'E:ESvideoili1.mp4', 'wb') as fp1: # 存音频
                fp1.write(res2.content)                
         
    6. 可以获得视频和音频文件,通过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分钟来合成.

    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)
  • 相关阅读:
    SQL COUNT() 语法
    SQL AVG 函数
    Android开发
    IIf 函数
    励志
    王者归来
    Java基础知识总结(绝对经典)
    LeetCode算法题-Third Maximum Number(Java实现-四种解法)
    LeetCode算法题-Fizz Buzz(Java实现)
    LeetCode算法题-Longest Palindrome(五种解法)
  • 原文地址:https://www.cnblogs.com/W-Y-C/p/13406392.html
Copyright © 2011-2022 走看看