python递归下载极速资源的电影

import requests
import re
import os
from concurrent.futures import ThreadPoolExecutor
from Crypto.Cipher import AES
from bs4 import BeautifulSoup

"""
专门下载   《极速资源》  的电影
1.首先进入要下载的某个电影的主页,将网址输入程序
2.运行get_name方法,获取电影播放地址(非m3u8地址),key播放地址,以及电影名字
3.运行get_m3u8,最终获取到的是一个装有ts地址的列表
4.运行thread_download,开始多线程下载ts文件,在调用download方法时,可能会得到一个空文件
5.运行thread_decode,开始多线程解码ts文件,如果ts文件本身是空,那么解码会失败,但不会报错
6.运行check_ts,检查是不是全部解码完成,通过os.path.isfile('文件路径')反馈会一个新的列表self.new_lst,
    接收的是解码未成功的ts文件名称是self.lst列表中的索引,如果服务器断限制了你的访问,这地方会很有意思,
    总之,只要服务器端不是完全切断网络连接,就一定能全部解码完成。
7.运行marge,大功告成.
后记:
    class实在是太好玩了,比函数好用多了
    如果电脑性能好的话,可以修改ThreadPoolExecutor(50)里面的数值,数值越大,速度越快
"""


class Application:
    def __init__(self, url):
        self.url = url
        self.new_lst = []  # 接收解码失败的文件
        self.i = 0  # 统计download函数被重复调用的次数
        self.j = 0  # 统计经过多少级解码才完成全部解码
        self.IV = b'0000000000000000'  # 源文件32位,更改成16位
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0'
        }

    def get_name(self):
        resp = requests.get(self.url, headers=self.headers)
        resp.close()
        # print(resp.text)
        bs = BeautifulSoup(resp.text, 'html.parser')
        self.url = bs.find('span', id='1_1t').text.split('$')[-1].strip()  # 这个地方必须要加strip()
        self.movie_name = bs.find('div', class_='vod-img').find('img').get('alt')  # 太好玩了,可以连续用find
        self.key_url = self.url + '/enc.key'

        # print(self.url)
        # print(self.key_url)

    def get_m3u8(self):
        resp = requests.get(url=self.url, headers=self.headers)
        resp.close()
        # print(resp.text)
        obj1 = re.compile("url: '(?P<m3u8_url>.*?)',", re.S)
        m3u8_url = obj1.search(resp.text).group('m3u8_url')
        # print(m3u8_url)
        resp1 = requests.get(m3u8_url, self.headers)
        resp1.close()
        # print(resp1.text)
        obj2 = re.compile('https://p.ji.*?\.ts')
        self.lst = obj2.findall(resp1.text)
        # print(self.lst)

    def thread_download(self):
        new_lst = []
        with ThreadPoolExecutor(50) as t:
            for k, v in enumerate(self.lst):
                t.submit(self.download, name=k, ts_url=v)
        for i in range(len(self.lst)):
            if os.path.isfile(f'video/{i}'):
                continue
            else:
                new_lst.append(i)
        if new_lst:
            print('==============================ts文件没有全部下载成功!======================================')
            print(new_lst)
        else:
            print('==============================ts文件全部下载成功!')

    def download(self, name, ts_url):
        try:  # 这个地方有可能下载不成功,但不会报错,会继续执行,最终获得一个空的ts文件
            resp = requests.get(ts_url, headers=self.headers, timeout=10)
            resp.close()
            with open(f'video/{name}', mode='wb') as f:
                f.write(resp.content)
                print(f'{name}下载成功')
        except Exception as e:
            self.i += 1
            self.download(name, ts_url)
            print(f'{name}下载失败,第{self.i}次重新调用download方法====================')

    def thread_decode_ts(self):
        self.j += 1
        resp = requests.get(self.key_url, headers=self.headers)
        resp.close()
        self.key = resp.content
        self.aes = AES.new(self.key, AES.MODE_CBC, self.IV)
        with ThreadPoolExecutor(50) as t:
            for i in range(len(self.lst)):
                t.submit(self.decode_ts, name=i)
        print(f'第{self.j}次解码完成!')

    def decode_ts(self, name):
        with open(f'video/{name}', 'rb') as f:
            de_ts = self.aes.decrypt(f.read())
            with open(f'video/{name}_1', 'wb') as f1:
                f1.write(de_ts)
        print(f'video/{name}解码成功')

    def marge(self):
        with open(f'video/{self.movie_name}.mp4', mode='wb') as f:
            for i in range(len(self.lst)):
                with open(f'video/{i}_1', mode='rb') as f1:
                    f.write(f1.read())
                os.remove(f'video/{i}')
                os.remove(f'video/{i}_1')
        print(f'{self.movie_name}下载完成!')

    def check_ts(self):
        for i in range(len(self.lst)):
            if not os.path.isfile(f'video/{i}_1'):
                self.new_lst.append(i)
        if self.new_lst:
            self.j += 1
            print('以下没有解码成功')
            print(self.new_lst)
            with ThreadPoolExecutor(50) as t:
                for j in self.new_lst:
                    t.submit(self.download, name=j, ts_url=self.lst[j])
            with ThreadPoolExecutor(50) as t:
                for j in self.new_lst:
                    t.submit(self.decode_ts, name=j)
            print(f'第{self.j}次解码完成!')
            self.new_lst = []
            self.check_ts()
        else:
            print('全部解码完成!!!')

    def main(self):
        self.get_name()
        self.get_m3u8()
        self.thread_download()
        self.thread_decode_ts()
        self.check_ts()
        self.marge()


if __name__ == '__main__':
    # url = 'https://www.jisuzy.com/index.php/vod/detail/id/67042.html?ac=detail'  # 下载单个电影,进入这个电影的主页面
    url = input('请输入要下载的电影网址:').strip()
    # url = 'https://play.jisuzyv.com/play/DdwGGY1d'  # 下载电视剧某一集 不能直接用了
    # key_url = url + '/enc.key'
    app = Application(url)
    app.main()

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值