• python高阶爬虫---视频类内容爬取(以BiliBili和城市影院为例说明)



    Author:qyan.li

    Date:2022.6.23

    Topic:python爬虫获取视频类内容(以BiliBili和城市影院为例讲解)

    一、写在前面

               ~~~~~~~~~~           最近放暑假,闲来无事,爬点东西来玩。这学期由于课程需要,多次用爬虫的技术来获取数据,但都是获取一些文字类的数据。突发奇想,自己想利用爬虫获取一些音视频类的数据。下面以BiliBili和城市影院为例,说明爬虫获取音视频的技术和方法。BiliBili的视频爬取教程参考自BiliBili视频(自己爬自己,哈哈哈),城市影院的视频爬取以BiliBili为启发,自己编写。代码仅供参考,不用做其他用途。

               ~~~~~~~~~~           BiliBili的视频爬取参考自B站,可根据索引连接对应至原视频教程,较为详细,因此不会作为本文讲解的重点,城市影院代码自己编写,其中存在自己的思考和尝试,因此会作为本文讲解的重点。

    二、BiliBili视频爬取

               ~~~~~~~~~~           BiliBili视频爬取参考的B站连接:【Python教程】Python视频类爬虫实战案例讲解,新手入门必学项目,手把手带你完成。(本视频中的案例仅作为技术分享,请勿模仿)_哔哩哔哩_bilibili

               ~~~~~~~~~~           此处粘贴一下爬取B站视频的源代码,方便大家参考借鉴:

    # -*-coding = utf-8-*-
    
    # Author:qyan.li
    # Date:2022/6/20 11:48
    # Topic:借助于python爬取B站视频(B站资源)
    # Reference:https://www.bilibili.com/video/BV1GF411c7dA?p=3&vd_source=98cb4eb5f0c21487fcbd999a5f430af1
    
    import requests
    import re
    import json
    import pprint
    import subprocess
    
    def askURL(url):
    
        head = {
                ## 此处设置防盗链:指明连接的请求来源于B站,合法
                'referer':
                'https://www.bilibili.com/',
                'user-agent':
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.124 Safari/537.36 Edg/102.0.1245.44'
        }
        response = requests.get(url = url,headers = head)
        return response
    
    def getVideoInfo(response):
        ## 正则表达式:用于匹配获取音频和视频地址
        findUrl = re.compile('<script>window.__playinfo__=(.*?)</script>')
        VideoInfo = re.findall(findUrl,response.text)[0]
        ## 字符串转换为python的数据类型,便于后续操作
        jsonData = json.loads(VideoInfo)
        return jsonData
    
    def download(jsonData):
        # print(type(jsonData))
        ## 解析获得音频和视频的url
        audioURL = jsonData['data']['dash']['audio'][0]['baseUrl']
        videoURL = jsonData['data']['dash']['video'][0]['baseUrl']
        print(audioURL)
        print(videoURL)
    
        ## 用于下载音频和视频信息
        audioContent = askURL(audioURL).content
        with open('./' + 'python教程' + '.mp3',mode = 'wb') as f:
            f.write(audioContent)
        videoContent = askURL(videoURL).content
        with open('./' + 'python教程' + '.mp4',mode = 'wb') as f:
            f.write(videoContent)
    
    ## 音视频合成参考:https://blog.csdn.net/weixin_43835542/article/details/109493050
    ## ffmpeg下载:https://blog.csdn.net/pythonlaodi/article/details/109222790
    ## 字符串前面加f:https://blog.csdn.net/qq_43463045/article/details/93890436
    ## (字符串中花括号中的部分可以正常的替换执行)
    def audioAndVideo(audioFile,videoFile):
        outfile_name = './output.mp4'
        cmd = fr'F:\CommonApp\ffmpeg\bin\ffmpeg.exe -i {audioFile} -i {videoFile} -acodec copy -vcodec copy {outfile_name}'
        print(cmd)
        subprocess.call(cmd,shell=True)
    
    
    def main():
        html = askURL(url = 'https://www.bilibili.com/video/BV1GF411c7dA')
        jsonData = getVideoInfo(html)
        ## pprint可以按照标准的方式打印字典,便于查阅
        pprint.pprint(jsonData)
        download(jsonData)
       	audioAndVideo(r'C:\Users\腻味\Desktop\VideoClawer\BiliBiliClawer\python教程.mp3',r'C:\Users\腻味\Desktop\VideoClawer\BiliBiliClawer\python教程.mp4')
        pass
    
    
    
    if __name__ == '__main__':
        main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    爬虫代码小Tips:

    1. head中不仅需要指明user-agent,还需要referer指明连接的请求来源于原网站,是合法的请求连接
    2. 至于我们为什么知道playinfo中包含我们所需要的url信息,原视频中未提及,应该是经过无数次的尝试和探索,寻找到的视频和音频连接
    3. playinfo中提取目标信息可能不具有普遍性,没有办法进行移植,但是download函数的编写和使用具有普遍性,可以通过此种方式完成借助于url下载所需要的音视频内容
    4. ffmpeg网络上称为音视频处理鼻祖级的存在,可以学习一下,方便后期的音视频处理使用

    三、城市影院爬取

               ~~~~~~~~~~           上面主要内容在于B站视频爬取,下面我们将以城市影院为例,借用上述B站爬取代码思想爬取城市影院电影。首先说明:下面的代码并非完整的爬虫代码,但可以保证获取到电影的音视频并且下载至本地。老样子,还是先上代码方便大家参考借鉴:

    ## Author:qyan.li
    ## Date:2022.6.22
    ## Topic:借助于python爬取city电影视频
    
    import requests
    import re
    import os
    import subprocess
    
    def askURL(url):
    
        head = {
                ## 此处设置防盗链:指明连接的请求来源于B站,合法
                'referer':
                'https://www.citydy.com/',
                'user-agent':
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.124 Safari/537.36 Edg/102.0.1245.44'
        }
        response = requests.get(url = url,headers = head)
        return response
    
    
    def readFile(filePath = ''):
        with open(filePath,'r') as f:
            urlString = f.readlines()
        urlLst = [string.strip('\n') for string in urlString if 'https' in string]
        return urlLst
    
    def VideoClawer(urlLst):
        with open('./全球风暴.mp4',mode = 'ab') as f:
            for i in range(len(urlLst)):
                videoContent = askURL(urlLst[i]).content
                f.write(videoContent)
                print(i)
    
    if __name__ == '__main__':
        content = readFile(filePath = './全球风暴.m3u8')
        VideoClawer(content)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    通过观察代码可以发现:

    城市影院视频爬取的思路与B站爬取类似,都是找到视频链接url,而后通过下载链接内容存入指定文件中实现(实际上,这种操作和思想本身借鉴于B站视频资源的爬取),但是区别体现在:

    • 城市影院音视频合并不分离,因此不需要分别下载音视频文件,而后再进行合并
    • 城市影院寻找m3u8文件,内含切片视频的链接,按照链接次序下载即可(有关m3u8文件的说明,可自行检索查询)

               ~~~~~~~~~~           下面我们开始主要说明m3u8文件的获取及解析,首先简单提一下m3u8文件,在视频播放时,为保证视频播放的流畅度,可以将一大段视频进行切片,形成若干的ts视频切片文件,视频播放时,按照顺序一段段播放ts文件即可,而m3u8文件即是存放ts文件的索引文件,其中包含切片视频文件ts的下载url,我们仅需要按照这些url下载对应的视频内容即可。

    我们以爬取城市影院(https://www.citydy.com)的全球风暴电影为例进行说明:

    1. 首先进入至城市影院,搜索全球风暴,打开电影播放界面,按下F12打开网络源码,点击网络(network),ctrl+R刷新界面:
      在这里插入图片描述

    2. 点击大小,将界面中请求按照从大到小的顺序排列,找到类型为xhr,文件大小最大的请求(图中红线标注的位置)

    在这里插入图片描述

    1. 点击此词条对应的名称进入,复制请求url(图中红线标注的位置),至浏览器搜索框进行下载

    在这里插入图片描述

    1. 下载完成后获得m3u8文件

    在这里插入图片描述

    关于m3u8文件的小Tips:

    • 其他音视频均可按照此方式查找并手动下载m3u8文件
    • m3u8文件下载时,如界面提示403 forbidden,可按照上述方式重新操作下载即可

               ~~~~~~~~~~           上面主要讲述如何从浏览器界面中获取m3u8文件,下面我们聚焦于m3u8文件的解析:

    • 打开下载完成的m3u8文件

    在这里插入图片描述

    其中红线标注的部分即为上面提到的切片视频的url链接,我们仅需要根据此链接下载视频内容即可,但是注意下载下仅为原视频的一段,大概也就10s左右

    • 提取链接,下载视频

      1. 首先提取出m3u8文件中所有的url链接(判断的方式是当前行中是否包含https字段)

        with open(filePath,'r') as f:
            urlString = f.readlines()
        urlLst = [string.strip('\n') for string in urlString if 'https' in string]
        
        • 1
        • 2
        • 3
      2. 根据提取到的url下载视频内容

        with open('./全球风暴.mp4',mode = 'ab') as f:
            for i in range(len(urlLst)):
                videoContent = askURL(urlLst[i]).content
                f.write(videoContent)
                print(i)
        
        • 1
        • 2
        • 3
        • 4
        • 5

        小Tips:

        1. 以二进制追加的形式打开,因为提取一段段视频至一个mp4文件中,必须以追加的形式写入(a),同时以二进制形式操作文件(b)
        2. print(i)是为观察视频下载进度设置
        3. 自己曾尝试将每个url都保存为一个mp4小文件,可以但是后续视频合并较为繁琐且难以操作,因此没有特殊需求不建议使用此方法
      3. 执行完上述操作,没有其他问题的情况下,应该可以成功下载视频


               ~~~~~~~~~~           最后大家可以回到下载m3u8的界面,点击播放按钮播放电影,可以观察右侧请求的变化:
    在这里插入图片描述

               ~~~~~~~~~~           在视频的播放过程中,可以看到,在m3u8文件下载链接的上方大概每隔几秒就会重新出现一个xhr,这个其实就是一个个的切片视频,大家如果感兴趣,可以按照此链接进行视频下载,可以获得某一段视频文件。实际上这个和我们m3u8文件中的链接是等价的,视频播放过程也侧面印证这一点。

  • 相关阅读:
    波卡三季度报告:已实现白皮书目标,异步支持与应用链技术推进
    Shell脚本中2>&1、>、>>等符号到底是什么含义
    nacos 与 seata 的整合
    [DebugMode]\RefreshMenu
    华为云云服务器评测 宝塔+nginx 同时部署Springboot、Vue项目
    现在的湖仓一体像是个伪命题
    AntDesignPro快速入门
    Mac OS 使用Metal渲染NV12、YUV420、CMSampleBufferRef视频
    第六章 数学(二)
    Oracle-单行函数大全
  • 原文地址:https://blog.csdn.net/DALEONE/article/details/125496552