python 爬虫学习--爬取m3u8视频文件

python 爬虫学习–爬取m3u8视频文件

之前学习了python爬虫,直到了you-get,但是有些网站还是获取不到,所以就又了解到了m3u8这种格式的视频流,学习着取爬了些小网站的视频。

m3u8文件获取

首先先去获取m3u8的一级网址(有的需要重定向,有的不需要),我的这个是需要重定向的,不需要重定向的话,直接获取就可以了。
注:因为不知道怎么正则表达式处理,所以就用了比较原始的方法取切片了,,,就最终效果来看还行

def get_m3u8_1(url):
    '''
    获取网站m3u8地址
    '''
    res = requests.get(url).text
    # print(res)
  
    s1 = "\"url\":\"h"
    s2 = "m3u8"
    # print(s1)
    
    s1_index = res.find(s1)
    s2_index = res.find(s2)
    # print(s1_index)
    # print(s2_index)
    s1_index+=7
    s2_index+=4

    ss = res[s1_index:s2_index]

    s3 = "\/"
    s4 = "/"
    r = ss.replace(s3,s4)

    return r

重定向后的地址获取

def get_m3u8_2(url):
    '''
    得到重定向后的m3u8地址
    '''
    res = requests.get(url).text
    # print(res)
    r = "https://xxx.xxxxx.com";
    # res.replace("\n","").replace("\r","")
    res_index = res.find("/")
    r = r + res[res_index:]
    return r

读取ts流文件

再从重定向后的网址,读取.ts文件就可以得到视频了,最后再进行合成,但是一般来说,如果进行加密了的话,合成后的mp4文件时没有办法看的(当然.ts也没有办法看),所以要进行解密,下面再讲。

.ts都在“EXTINF”的下一行,自己用一种方法读取就行了。我这里就还是使用的find,然后找到直接定位到下一行。

具体代码放到下面整体实现了(download函数)

获取密钥并解密

m3u8文件内容信息这里就不说了,主要说key的一行,有个key.key结尾的网址,那里是存的密钥,先读出来,方便下面解密。

获取密钥的代码如下

def get_key(url):
    res = requests.get(url).text
    # print(res)
    s1 = "URI"
    s1_index = res.find(s1)+5
    s2 = "key.key"
    s2_index = res.find(s2)+7
    re = res[s1_index:s2_index]
    # print(r)
    headers = {
     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.47'}

    r = requests.get(re,headers=headers).text
    return r
    

然后是解密,有的是有偏移量IV的,这个在之前的m3u8文件可以看到,key后面如果还有一栏那就是有IV,这个偏移量是解密的第三个参数,第一个就是key。然后开始解密。

python解密要先读入AES包 from Crypto.Cipher import AES,报错,使用pip安装下这个包,注意,名字变啦,现在的名字是这个:pycryptodome。

如果报错“ cannot be passed to C code”了,编码问题,我这里加了.decode(“utf-8”)就解决了。

具体代码实现放到后面了。
下载完所有的.ts文件在使用系统命令copy合并成mp4就完成了。

全部代码见下

网址随便写的,然后因为是python新手,注释还有命名有很多不规范的地方。
# -*- coding: utf-8 -*-
# Created on 2021/5/24
 
 
import requests
import os
from Crypto.Cipher import AES

 
def get_m3u8_1(url):
    '''
    获取网站m3u8地址
    '''
    res = requests.get(url).text
    # print(res)
  
    s1 = "\"url\":\"h"
    s2 = "m3u8"
    # print(s1)
    
    s1_index = res.find(s1)
    s2_index = res.find(s2)
    # print(s1_index)
    # print(s2_index)
    s1_index+=7
    s2_index+=4

    ss = res[s1_index:s2_index]

    s3 = "\/"
    s4 = "/"
    r = ss.replace(s3,s4)

    return r
def get_m3u8_2(url):
    '''
    得到重定向后的m3u8地址
    '''
    res = requests.get(url).text
    # print(res)
    r = "https://xxx.xxxxx.com";
    # res.replace("\n","").replace("\r","")
    res_index = res.find("/")
    r = r + res[res_index:]
    return r

def get_key(url):
	‘’‘
	获取密钥
	’‘’
    res = requests.get(url).text
    # print(res)
    s1 = "URI"
    s1_index = res.find(s1)+5
    s2 = "key.key"
    s2_index = res.find(s2)+7
    re = res[s1_index:s2_index]
    # print(r)
    headers = {
     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.47'}

    r = requests.get(re,headers=headers).text
    return r
    
    
def download(url,ttt):

    url1 = get_m3u8_1(url)

    url2 = get_m3u8_2(url1)
    
    file_path = os.getcwd()+"/download"


    key =  get_key(url2).encode("utf-8")
    
    sd = "EXTINF"
    res = requests.get(url2).text

    sd_index = 0
    sdc = 0
    
    while 1:
        sd_index = res.find(sd,sd_index)
        sdc+=1
        
        if sd_index == -1:
           break
        sd_index+=1

    # print(sdc)
    # return
    s1 = "https"
    s2 = ".ts"
    s1_index = res.find(s1,0)
    s1_index+=5
    s1_index = res.find(s1,s1_index)
    s2_index = res.find(s2,0)

    cnt = 0;
    while 1:
        s2_index+=3
        ss = res[s1_index:s2_index]
       
        s1_index = res.find(s1,s1_index+1)
        
        s2_index = res.find(s2,s2_index)
        if s2_index == -1:
            break
            
        cryptor = AES.new(key,AES.MODE_CBC,key) # 解密
        res1 = requests.get(ss)
        
        with open(file_path+"//"+str(cnt)+".ts","ab") as f:
            f.write(cryptor.decrypt(res1.content))
            cnt+=1
            os.system("CLS")
            print("<--<--<--<--<--<--<--",end="")
            print(cnt,end="")
            print("-->-->-->-->-->-->-->")

            print("<--<--<--<--<--<--<--",end="")
            print(sdc,end="")
            print("-->-->-->-->-->-->-->")
            # print(sdc)
 
    
    f.close()
    mege(file_path,ttt)

def mege(file_path,cnt):
    '''
    合并文件
    '''
    file_name = str(cnt)+".mp4"
    os.chdir(file_path)
    os.system("copy /b *.ts new.tmp")
    os.system("del /Q *.ts")
    os.rename("new.tmp",file_name)
    
if __name__ == '__main__':
    index = 13589
    cnt = 0
    
    # 这里是只下载了三个网页的视频做了测试
    while 1:
        cnt+=1
        url = "https://www.xxxx.xxxx/index.php/vod/play/id/"+str(index)+"/sid/1/nid/1.html"
        download(url,cnt)
        index+=1
        if cnt == 3:
            break

遗留问题

1、下载的视频只有5分钟,不知道为什么,可能是m3u8文件没有找全,不太清楚。
2、效率应该相当的低。不过学习记录一下罢了。仅仅是因为学习了爬虫感觉很好玩qwq

你可能感兴趣的:(python,爬虫)