吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12375|回复: 56
收起左侧

[Python 原创] python实现下载 pp视频(pptv聚力)付费视频(蓝光画质)

  [复制链接]
wshuo 发表于 2020-5-1 03:18
源码地址:https://ww.lanzouj.com/ic4v7yd
里面包含了项目源码及ffmpeg,和我写的一个自动安装ffmpeg的脚本并设置环境变量(原理就是通过修改注册表来添加环境变量),运行一下就可以了,可以在cmd 输入ffmpeg测试是否成功(主要是针对windows平台的)

前言

前几天我想看一个番剧, 正好搜索到了 PP视频,我才知道PP视频就是PPTV聚力,我想把番剧下载下来,结果发现视频竟然不是m3u8格式,而是多段mp4,所以简单的写了个脚本,可以在不登录的情况下直接下载vip和付费视频蓝光画质(只能说明这个视频网站做的不行)

开始分析

经过调试我首先得到了视频地址的url
https://10314.vcdn.pplive.cn/0/0/1/2de8f8694a79c437a11b09941fb1cb0a.mp4?h5vod.ver=2.1.3&k=0b6a74e50374776203bd05d55a090fba-e800-1588284812&type=mhpptv

当然,我当时拿到的url 是很长的一段还有其他参数,但是我发现那些参数都是无用的影响访问的参数只有这几个
h5vod.ver : 固定值
type : 固定值
k : 变值

说明 k 是一个接口得到的, 所以我需要找到对应的接口就可以了

但是现在还有一个问题就是 这个只是视频的一段, 其他视频分段地址又是什么样的呢?
经过我反复调试发现 url 中的
https://10314.vcdn.pplive.cn/a/b/c/
(对应位置我用字母来代替数字了,为了描述方便)
a 为分段视频的第几段
b 默认为0 就可以(具体表示什么不清楚,但是瞎填肯定是不行的)
c 这个数字可以随意瞎填,因为后台解析没用到这个参数,但是要有这个参数
a 为 0 为第一段视频, a 为 1 为第二段视频

所以接下来的问题就是找到那个接口了
经过调试发现了一个接口
https://web-play.pptv.com/webplay3-0-12407631.xml?o=0&version=6&type=mhpptv&appid=pptv.web.h5&appplt=web&appver=4.0.7&cb=a
这个接口参数只有一个变量 那就是12407631,也就是id,每一集都有唯一的 id ,而这个id 我们也可以通过访问对应视频播放界面的url后返回的html源码中查看到
在这里插入图片描述
返回的不只是一集,而是全剧的每一集id都可以通过一个url来获取到

那么我们来看看 这个接口返回了哪些内容
在这里插入图片描述
几种画质的 mp4,知道这些那么我们还查一个 k参数就可以构造视频的url了
经过我查找发现了k值, 一个视频的一种清晰度对应唯一一个k值
在这里插入图片描述
这里用了url编码看起来乱七八糟,用python解码一下

from urllib.parse import unquote
print(unquote("4e6a8848fb388e09708a132bf4caeb4e-5775-1588285899%26bppcataid%3D17"))

输出:

4e6a8848fb388e09708a132bf4caeb4e-5775-1588285899&bppcataid=17

可以看到 & 符号前面的就是k ,所以到时候我们可以用& 进行分割然后取 k

到此看起来问题全部解决了我们也可以构造视频url 了,但是还有一个问题, 那就是视频到底分多少段我们还不知道, 毕竟我们不能遍历去访问直到访问不到数据(那样太傻了)

其实接口里面也存在这样的数据了
在这里插入图片描述
画质下面mp4 字段 childNodes 是一个列表,这个列表的长度减1 就是不同画质的分段数, 减1 是因为最后一个元素是别的内容不是描述视频分段信息的, 不得不说这个接口返回的数据构造的真是及其混乱, 我解析的时候都费了很大劲!

到此问题全部解决

代码实现

import requests
import re
import json
import os
from threading import Thread
import sys

import time

requests.packages.urllib3.disable_warnings()

def progress():
    width=30
    while True:
        global all_num
        global now_num
        percent = now_num/all_num * 100
        left = int(width * percent // 100)
        right = width - left
        print('\r[', '#' * left, ' ' * right, ']',f' {percent:.0f}%',sep='', end='', flush=True)
        if all_num == now_num:
            break
        time.sleep(1)

def hecheng(sh,path):
    # 判断是否只是一段视频
    if len(os.listdir(path)) <= 2:
        os.remove(path+os.sep+"1.txt")
    else:
        os.system(sh)
        for i in os.listdir(path):
            if i != 'output.mp4':
                os.remove(path+os.sep+i)

def download(url,id_,name):
    global now_num
    data = requests.get(url,headers={"Range": "bytes=0-"},stream=True).content
    with open(name+os.sep+str(id_)+'.mp4','wb') as f:
        f.write(data)
    now_num += 1

def api_get(id_):
    global all_num   
    global now_num
    all_num = 0
    now_num = 0

    api_url = f"https://web-play.pptv.com/webplay3-0-{id_}.xml?o=0&version=6&type=mhpptv&appid=pptv.web.h5&appplt=web&appver=4.0.7&cb=a"
    s = requests.get(api_url,verify=False,headers=headers)
    data = json.loads(s.text[2:-4])
    try:
        name = data['childNodes'][2]['nm']
    except Exception:
        name = data['childNodes'][0]['nm']
    print("正在下载:"+name)

    rid = data['childNodes'][-4]['rid']
    all_num = len(data['childNodes'][-4]['childNodes']) -1
    kk = data['childNodes'][-5]['childNodes'][-1]['childNodes'][0].split('%26')[0]
    if not os.path.exists(name):
        os.makedirs(name)

    # 合成命令
    a1 = os.path.abspath(name+os.sep+'1.txt')
    a2 = os.path.abspath(name+os.sep+'output.mp4')
    sh = f'ffmpeg -f concat -safe 0 -i "{a1}" -c copy "{a2}" -loglevel error'
    path = os.path.dirname(a1)

    # 启动进度条线程
    progress_t = Thread(target=progress)
    progress_t.start()

    t_list = []
    t_list.append(progress_t)

    f = open(name+os.sep+'1.txt','w')
    for i in range(all_num):
        video_url = f"https://10314.vcdn.pplive.cn/{i}/0/1/{rid}?h5vod.ver=2.1.3&k={kk}&type=mhpptv"
        f.write("file "+ os.path.abspath(name+os.sep+f'{i}.mp4')+"\n")

        t = Thread(target=download,args=(video_url,i,name))
        t_list.append(t)
        t.start()

        if not mul_t:
            t.join()

    f.close()   
    for t in t_list:
        t.join()

    # print(sh)
    print("\n"+name+" 正在合成...")
    hecheng(sh,path)
    print(name+" 合并成功")

def start(url,is_all,s,e,mul_t):
    response = requests.get(url,verify=False,headers=headers)
    if response.status_code == 200:
        result = re.findall("var webcfg = (.*?);",response.text)
        data = json.loads(result[0])

        if is_all:
        # 下载剧集
            try:
                for item in data['playList']['data']['list'][s-1:e]:
                    api_get(item['id'])
            except Exception:
                for item in data['playList']['data']['list']:
                    api_get(item['id'])
        else:
        # 下载单集
            api_get(data['id'])

if __name__ == "__main__":
    all_num = 0
    now_num = 0
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
    }

    url = input("输入地址:")
    is_all = input("是否下载全剧(默认否):")
    if is_all:
        r = input("请输入下载剧集(例如1-5,默认全部):")
        if r:
            s,e = r.split("-")    
            s = int(s)
            if e:
                e = int(e)
            else:
                e = None
        else:
            s = None
            e = None

    mul_t = input("是否启用多线程下载(默认否):")
    start(url,is_all,s,e,mul_t)

也是做了一个简单的命令行工具,功能有

  1. 通过一次输入可以下载全集的蓝光画质视频
  2. 下载vip 视频
  3. 下载付费视频
  4. 下载完分段视频自动调用 ffmpeg 命令进行合成
  5. 选择性 下载 m-n  集视频
  6. 多线程下载(下载电影时候最好不要开启)

使用方法: 视频播放界面的url输入进去,然后回车, 剩下的参数不写直接回车相当于默认, 随意写什么相当与

其他注意 : windows 使用调用 ffmpeg先要把其加入系统环境变量里面,另外 第 81 行代码应改为

f.write("file "+ (os.path.abspath(name+os.sep+f'{i}.mp4')+"\n").replace("\\","\\\\"))

这个主要是windows  脑残的文件路径问题

免费评分

参与人数 17威望 +1 吾爱币 +27 热心值 +15 收起 理由
jly123 + 1 + 1 谢谢@Thanks!
cxkj1225 + 1 + 1 谢谢@Thanks!
袁昌旺 + 1 + 1 我很赞同!
zjia + 1 + 1 我很赞同!
aaa12345678 + 1 + 1 谢谢@Thanks!
luying5267 + 1 + 1 我很赞同!
苏紫方璇 + 1 + 10 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
fanvalen + 1 视频网为了大小居然改用h264编码了
飞鲲之梦 + 1 我很赞同!感觉很快就会被修复
fhy129 + 1 + 1 热心回复!
白书 + 1 + 1 python的基础教程
fckinnocent + 1 + 1 热心回复!
hash多多 + 1 + 1 都是狠人
xhy13721357088 + 1 我很赞同!
一剑封侯人 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
wkfy + 3 + 1 热心回复!
webber.yan + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
TicketForLife 发表于 2020-12-29 18:13
提示: 作者被禁止或删除 内容自动屏蔽
 楼主| wshuo 发表于 2020-5-2 23:30
那年夏天52 发表于 2020-5-2 16:39
Traceback (most recent call last):
  File "C:%users\Administrator\Desktop\pp视频\main.py", line 156 ...

这个说明你输入有问题,在分集下载的时候输入格式为:1-10,然后回车,这样会下载1-10集,如果什么都不输入下载全剧(什么都不输入可以直接回车)
webber.yan 发表于 2020-5-1 03:55
虽然没有看懂,但是感谢楼主的分享,幸苦了
jp84058481 发表于 2020-5-1 06:31
这个支持
tzg2008 发表于 2020-5-1 06:52
非常好的代码!支持一下
psfzq 发表于 2020-5-1 07:01
谢谢分享,就是不明白,好好学习。
老狼客 发表于 2020-5-1 07:06
支持支持,学习就是动力!
Jason68258 发表于 2020-5-1 07:23
谢谢楼主分享
一剑封侯人 发表于 2020-5-1 07:27
楼主可否来个安卓版
xiong779 发表于 2020-5-1 07:55
感谢楼主的分享,幸苦了
Ldfd 发表于 2020-5-1 08:01
you-get不香吗
感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 07:48

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表