爬虫爬取电影,下载ts并合并ts实例

采用协程方式来爬取ts文件,大大提高了爬取的效率

本次爬取电影内容有key加密,对ts文件进行了解密,并将ts文件合并成mp4视频

代码如下:建议从下往上看

import asyncio                      #协程的模块
import requests
import re
from Crypto.Cipher import AES       #安装pycryptodome,用来解密的模块
import aiofiles                     #用来协程打开文件
import aiohttp                      #用来协程请求url
import os

def craw_m3u8(m3u8_url):
    '''
    抓取m3u8文件,将里面内容写入文件里
    '''
    headers={
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
    }
    #https://play.subokk.com/play/QbYL1EOa/index.m3u8
    # return "https:\/\/play.subokk.com\/play\/QbYL1EOa\/index.m3u8"
    rep=requests.get(m3u8_url,headers=headers)                                  #访问m3u8的url
    with open('m3u8.txt','w',encoding='utf-8') as f:
        f.write(rep.text)
    return 'm3u8.txt'
    
    

async def download(line,session):
    ''' 下载一个ts视频  '''

    filename = line.split('/')[-1]                           #取文件名
    async with session.get(line) as r:
        async with aiofiles.open(f'vide/{filename}','wb') as f:
            await f.write(await r.content.read())            #因为文件写入还是文件读取都是异步的,所以需要await
    # print(f'{filename}ok')



async def craw_ts(file):

    ''' 读取文件里的每一个ts并访问,将视频下载到新的文件里'''

    async with aiohttp.ClientSession() as session:      #在这里创建requests模块,这样只需要创建一次,如果在download里面创建则每一次循环都得创建一次
        tasks=[]
        async with aiofiles.open(file,'r',encoding='utf-8') as f:
            async for line in f:
                line=line.strip()               #去掉空格跟换行符号
                if line.startswith('#'):
                    continue

                #异步协程下载每一个视频内容
                task=asyncio.create_task(download(line,session))       #download函数是下载一个视频
                tasks.append(task)
            await asyncio.wait(tasks)



def get_key(key_url):
	'''解析key的url,拿到key的内容'''
    re=requests.get(key_url)
    return re.text
    
    
async def dec_ts(filename,key):
    '''解密单个视频并写入文件'''
    key=bytes(key,'utf-8')      #aes.new()里面的key,IV都是传入字节形式
    aes=AES.new(key=key,IV=bytes("0000000000000000",'utf-8'),mode=AES.MODE_CBC)       #IV中的0个数是看key的长度
    async with aiofiles.open(f'vide/{filename}','rb') as f1,\
            aiofiles.open(f'vide/tem_{filename}','wb') as f2:
        bs=await f1.read()                  #从源文件里读取内容
        await f2.write(aes.decrypt(bs))     #把解密好的东西写入f2中
    print(f'{filename},ok')


async def aio_dec(key):
    '''解密       异步携程操作'''
    tasks=[]
    async with aiofiles.open('m3u8.txt','r',encoding='utf-8') as f:
        async for line in f:
            if line.startswith('#'):
                continue
            line=line.strip()
            filename = line.split('/')[-1]
            task=asyncio.create_task(dec_ts(filename,key))             #dec_ts()函数是解密一个ts文件视频
            tasks.append(task)
        await asyncio.wait(tasks)


def merge_ts():
    '''
    将ts合并成mp4视频
    windows:copy /b 1.ts+2.ts+3.ts xxx.mp4
    '''
    lst=[]
    with open('m3u8.txt','r',encoding='utf-8') as f:
        for line in f:
            if line.startswith('#'):
                continue
            line=line.strip()
            filename=line.split('/')[-1]
            lst.append(f'vide/tem_{filename}')
    s="+".join(lst)
    os.system(f"copy /b {s} movie.mp4")
    print('ok')


def merger():
    ''' 将所有ts文件合成视频MP4文件'''

    with open("vide/movie.mp4", "wb") as f:                 #创建一个mp4文件,将ts以二进制格式写入
        with open("m3u8.txt", "r") as f1:
            for line in f1:
                if line.startswith("#"):
                    continue
                line = line.strip()
                name = line.split('/')[-1]
                with open(f'vide/tem_{name}', "rb") as f2:      #以二进制格式读取ts文件
                    f.write(f2.read())


def main(url):
    '''
    1.访问url,得到页面源码
    2.解析源码拿到m3u8的url
    3.访问m3u8的url,将内容写入文件
    4.拿到文件里的每一个ts的url,请求并以二进制下载ts文件
    5.拿到密钥url,访问url并拿到密钥的内容
    6.对ts进行解密
    7.将所有解密好的ts文件进行合并成mp4文件
    '''
    r=requests.get(url)
    obj=re.compile(r'4f5c"},"url":"(?P<url_>.*)","url_next',re.S)        #提取m3u8的地址
    m3u8_url=obj.search(r.text).group('url_').replace("\/",'/')
    m3u8=craw_m3u8(m3u8_url)          #抓取m3u8的文件,将内容写入文件里

    #下载所有的ts视频文件
    # craw_ts(m3u8)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(craw_ts(m3u8))        #异步协程来下载所有ts文件视频

    #拿到密钥
    key_url=os.path.dirname(m3u8_url)+'/enc.key'        #密钥key的url
    key=get_key(key_url)                                #访问并拿到key文件里的内容
    #解密
    asyncio.run(aio_dec(key))                           #解密ts文件并生成另一些解密好的文件

    #合并解密好的ts文件为mp4文件视频
    merger()                    #我用了merge_ts()方法合并视频但没有用,所以我用二进制读取方式将每一个ts内容放在MP4文件里


#https://play.subokk.com/play/QbYL1EOa/enc.key
#https://play.subokk.com/play/QbYL1EOa/index.m3u8

if __name__=='__main__':
    url='https://www.shuangbodb.com/98ju/47235-2-1.html'
    main(url)

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐