更新 'iqy.py'

main
Violet 6 months ago
parent 038118e3f0
commit 2f1ca99981
  1. 593
      iqy.py

593
iqy.py

@ -1,296 +1,297 @@
import base64 import base64
import json import json
import time import time
from urllib import parse from urllib import parse
import requests import requests
from tabulate import tabulate from tabulate import tabulate
from pywidevineb.L3.cdm import deviceconfig from pywidevine.L3.cdm import deviceconfig
from pywidevineb.L3.decrypt.wvdecryptcustom import WvDecrypt from pywidevine.L3.decrypt.wvdecryptcustom import WvDecrypt
from tools import dealck, md5, get_size, get_pssh from tools import dealck, md5, get_size, get_pssh
def get_key(pssh): def get_key(pssh):
LicenseUrl = "https://drml.video.iqiyi.com/drm/widevine?ve=0" LicenseUrl = "https://drml.video.iqiyi.com/drm/widevine?ve=0"
wvdecrypt = WvDecrypt(init_data_b64=pssh, device=deviceconfig.device_android_generic) wvdecrypt = WvDecrypt(init_data_b64=pssh, cert_data_b64="",device=deviceconfig.device_android_generic)
widevine_license = requests.post(url=LicenseUrl, data=wvdecrypt.get_challenge()) widevine_license = requests.post(url=LicenseUrl, data=wvdecrypt.get_challenge())
license_b64 = base64.b64encode(widevine_license.content) license_b64 = base64.b64encode(widevine_license.content)
wvdecrypt.update_license(license_b64) wvdecrypt.update_license(license_b64)
correct, keys = wvdecrypt.start_process() correct, keys = wvdecrypt.start_process()
for key in keys: for key in keys:
print('--key ' + key) print('--key ' + key)
key_string = ' '.join([f"--key {key}" for key in keys]) key_string = ' '.join([f"--key {key}" for key in keys])
return key_string return key_string
class iqy: class iqy:
def __init__(self, aqy): def __init__(self, aqy):
self.ck = aqy self.ck = aqy
ckjson = dealck(aqy) ckjson = dealck(aqy)
self.P00003 = ckjson.get('P00003', "1008611") self.P00003 = ckjson.get('P00003', "1008611")
self.pck = ckjson.get('P00001') self.pck = ckjson.get('P00001')
self.dfp = ckjson.get('__dfp', "").split("@")[0] self.dfp = ckjson.get('__dfp', "").split("@")[0]
self.QC005 = ckjson.get('QC005', "") self.QC005 = ckjson.get('QC005', "")
self.requests = requests.Session() self.requests = requests.Session()
self.requests.headers.update({
self.requests.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", })
"Cookie": self.ck, self.bop = f"{{\"version\":\"10.0\",\"dfp\":\"{self.dfp}\",\"b_ft1\":8}}"
})
self.bop = f"{{\"version\":\"10.0\",\"dfp\":\"{self.dfp}\",\"b_ft1\":8}}" @staticmethod
def parse(shareurl):
@staticmethod try:
def parse(shareurl): url = "https://iface2.iqiyi.com/video/3.0/v_play"
try: params = {
url = "https://iface2.iqiyi.com/video/3.0/v_play" "app_k": "20168006319fc9e201facfbd7c2278b7",
params = { "app_v": "8.9.5",
"app_k": "20168006319fc9e201facfbd7c2278b7", "platform_id": "10",
"app_v": "8.9.5", "dev_os": "8.0.1",
"platform_id": "10", "dev_ua": "Android",
"dev_os": "8.0.1", "net_sts": "1",
"dev_ua": "Android", "secure_p": "GPhone",
"net_sts": "1", "secure_v": "1",
"secure_p": "GPhone", "dev_hw": "{\"cpu\":0,\"gpu\":\"\",\"mem\":\"\"}",
"secure_v": "1", "app_t": "0",
"dev_hw": "{\"cpu\":0,\"gpu\":\"\",\"mem\":\"\"}", "h5_url": shareurl
"app_t": "0", }
"h5_url": shareurl response = requests.get(url, params=params)
} data = response.json()
response = requests.get(url, params=params) pid = data['play_pid']
data = response.json() aid = data['play_aid']
pid = data['play_pid'] tvid = data['play_tvid']
aid = data['play_aid'] Album = data['album']
tvid = data['play_tvid'] Title = Album['_t']
Album = data['album'] Cid = Album['_cid']
Title = Album['_t'] return pid, aid, tvid, Title, Cid
Cid = Album['_cid'] except Exception as e:
return pid, aid, tvid, Title, Cid print(e)
except Exception as e: return None, None, None, None, None
print(e)
return None, None, None, None, None @staticmethod
def get_avlistinfo(title, albumId, cid, pid):
@staticmethod rets = []
def get_avlistinfo(title, albumId, cid, pid): page = 1
rets = [] size = 200
page = 1
size = 200 def getlist6():
url = "https://pcw-api.iqiyi.com/album/source/svlistinfo"
def getlist6(): params = {
url = "https://pcw-api.iqiyi.com/album/source/svlistinfo" "cid": "6",
params = { "sourceid": pid,
"cid": "6", "timelist": ",".join([str(i) for i in range(2000, 2026)]),
"sourceid": pid, }
"timelist": ",".join([str(i) for i in range(2000, 2026)]), response = requests.get(url, params=params)
} data = response.json()['data']
response = requests.get(url, params=params) for a, b in data.items():
data = response.json()['data'] for i in b:
for a, b in data.items(): ret = {
for i in b: "album": title,
ret = { "name": i['name'],
"album": title, "tvId": i['tvId'],
"name": i['name'], }
"tvId": i['tvId'], rets.append(ret)
}
rets.append(ret) def getlist():
aid = albumId
def getlist(): url = "https://pcw-api.iqiyi.com/albums/album/avlistinfo"
aid = albumId params = {
url = "https://pcw-api.iqiyi.com/albums/album/avlistinfo" "aid": aid,
params = { "page": page,
"aid": aid, "size": size
"page": page, }
"size": size response = requests.get(url, params=params).json()
} if response['code'] != 'A00000':
response = requests.get(url, params=params).json() return None
if response['code'] != 'A00000': data = response['data']
return None total = data['total']
data = response['data'] if total > size:
total = data['total'] for i in range(2, total // size + 2):
if total > size: params['page'] = i
for i in range(2, total // size + 2): response = requests.get(url, params=params).json()
params['page'] = i data['epsodelist'].extend(response['data']['epsodelist'])
response = requests.get(url, params=params).json() for i in data['epsodelist']:
data['epsodelist'].extend(response['data']['epsodelist']) ret = {
for i in data['epsodelist']: "album": title,
ret = { "name": i['name'],
"album": title, "tvId": i['tvId'],
"name": i['name'], }
"tvId": i['tvId'], rets.append(ret)
}
rets.append(ret) if cid == 1:
ret = {
if cid == 1: "album": title,
ret = { "name": title,
"album": title, "tvId": albumId,
"name": title, }
"tvId": albumId, rets.append(ret)
} elif cid == 6:
rets.append(ret) getlist6()
elif cid == 6: else:
getlist6() getlist()
else: return rets
getlist()
return rets def get_param(self, tvid="", vid=""):
tm = str(int(time.time() * 1000))
def get_param(self, tvid="", vid=""): authKey = md5("d41d8cd98f00b204e9800998ecf8427e" + tm + str(tvid))
tm = str(int(time.time() * 1000)) params = {
authKey = md5("d41d8cd98f00b204e9800998ecf8427e" + tm + str(tvid)) "tvid": tvid,
params = { "bid": "800",
"tvid": tvid, "src": "01010031010000000000",
"bid": "600", "uid": self.P00003,
"vid": "", "k_uid": self.QC005,
"src": "01010031010000000000", "authKey": authKey,
"vt": "0", "dfp": self.dfp,
"rs": "1", "pck": self.pck,
"uid": self.P00003, "vid": "",
"ori": "pcw", "tm": tm,
"ps": "0", "vt": "0",
"k_uid": "dc7c8156286e94182d2843ada4ef6050", "rs": "1",
"pt": "0", "ori": "pcw",
"d": "0", "ps": "1",
"s": "", "pt": "0",
"lid": "0", "d": "0",
"cf": "0", "s": "",
"ct": "0", "lid": "0",
"authKey": authKey, "cf": "0",
"k_tag": "1", "ct": "0",
"dfp": self.dfp, "k_tag": "1",
"locale": "zh_cn", "locale": "zh_cn",
"pck": self.pck, "k_err_retries": "0",
"k_err_retries": "0", "up": "",
"up": "", "sr": "1",
"sr": "1", "qd_v": "5",
"qd_v": "5", "qdy": "u",
"tm": tm, "qds": "0",
"qdy": "u", "k_ft1": "706436220846084",
"qds": "0", "k_ft4": "1162321298202628",
"ppt": "0", "k_ft2": "262335",
"k_ft1": "706436220846084", "k_ft5": "134217729",
"k_ft4": "1162321298202628", "k_ft6": "128",
"k_ft2": "262335", "k_ft7": "688390148",
"k_ft5": "134217729", "fr_300": "120_120_120_120_120_120",
"k_ft6": "128", "fr_500": "120_120_120_120_120_120",
"k_ft7": "688390148", "fr_600": "120_120_120_120_120_120",
"fr_300": "120_120_120_120_120_120", "fr_800": "120_120_120_120_120_120",
"fr_500": "120_120_120_120_120_120", "fr_1020": "120_120_120_120_120_120",
"fr_600": "120_120_120_120_120_120", }
"fr_800": "120_120_120_120_120_120", dash = f'/dash?'
"fr_1020": "120_120_120_120_120_120", for a, b in params.items():
} dash += f"{a}={b}&"
dash = f'/dash?' dash = dash[:-1] + "&bop=" + parse.quote(self.bop) + "&ut=13&ut=4&ut=5&ut=14&ut=57"
for a, b in params.items(): vf = md5(dash + "tle8orw4vetejc62int3uewiniecr18i")
dash += f"{a}={b}&" dash += f"&vf={vf}"
dash = dash[:-1] + "&bop=" + parse.quote(self.bop) + "&ut=14" return dash
vf = md5(dash + "tle8orw4vetejc62int3uewiniecr18i")
dash += f"&vf={vf}" def get_dash(self, tvid="", vid=""):
return dash params = self.get_param(tvid=tvid, vid=vid)
url = "https://cache.video.iqiyi.com" + params
def get_dash(self, tvid="", vid=""): res = self.requests.get(url)
params = self.get_param(tvid=tvid, vid=vid) return res.json()
url = "https://cache.video.iqiyi.com" + params
res = self.requests.get(url) def run(self, url=None):
return res.json() url = input("请输入爱奇艺分享链接:") if url is None else url
pid, aid, tvid, title, cid = self.parse(url)
def run(self, url=None): if pid is None:
url = input("请输入爱奇艺分享链接:") if url is None else url print("解析失败")
pid, aid, tvid, title, cid = self.parse(url) return
if pid is None: avlist = self.get_avlistinfo(title, aid, cid, pid)
print("解析失败") if avlist is None:
return print("获取列表失败")
avlist = self.get_avlistinfo(title, aid, cid, pid) return
if avlist is None: table = tabulate(avlist, headers="keys", tablefmt="grid", showindex=range(1, len(avlist) + 1))
print("获取列表失败") print(table)
return index = input("请输入序号:")
table = tabulate(avlist, headers="keys", tablefmt="grid", showindex=range(1, len(avlist) + 1)) index = index.split(",")
print(table) for i in index:
index = input("请输入序号:") if i.isdigit():
index = index.split(",") i = int(i)
for i in index: if i > len(avlist):
if i.isdigit(): print("序号错误")
i = int(i) continue
if i > len(avlist): tvId = avlist[i - 1]['tvId']
print("序号错误") name = avlist[i - 1]['name']
continue ctitle = avlist[i - 1]['album']
tvId = avlist[i - 1]['tvId'] print(f"正在获取{ctitle} {name}的m3u8")
name = avlist[i - 1]['name'] response = self.get_dash(tvid=tvId)
ctitle = avlist[i - 1]['album'] try:
print(f"正在获取{ctitle} {name}的m3u8") if response['data']['boss_ts']['code'] != 'A00000':
response = self.get_dash(tvid=tvId) print(f'获取m3u8失败\n')
try: print(response['data']['boss_ts']['msg'])
if response['data']['boss_ts']['code'] != 'A00000': continue
print(f'获取m3u8失败\n') except:
print(response['data']['boss_ts']['msg']) pass
continue data = response['data']
except: program = data['program']
pass if 'video' not in program:
data = response['data'] print("无视频")
program = data['program'] continue
if 'video' not in program: video = program['video']
print("无视频") audio = program['audio']
continue stl = program.get("stl", [])
video = program['video'] '''
audio = program['audio'] list = []
stl = program.get("stl", []) for a in video:
''' scrsz = a.get('scrsz', '')
list = [] size = a['vsize']
for a in video: vid = a['vid']
scrsz = a.get('scrsz', '') list.append((scrsz, vid, size))
size = a['vsize'] list.sort(key=lambda x: x[-1], reverse=True)
vid = a['vid'] tb = tabulate(list, headers=["分辨率", "vid", "大小"], tablefmt="grid",
list.append((scrsz, vid, size)) showindex=range(1, len(list) + 1))
list.sort(key=lambda x: x[-1], reverse=True) print(tb)
tb = tabulate(list, headers=["分辨率", "vid", "大小"], tablefmt="grid", index = input("请输入序号:")
showindex=range(1, len(list) + 1)) index = index.split(",")
print(tb) for i in index:
index = input("请输入序号:") vid = list[int(i) - 1][1]
index = index.split(",") response = self.get_dash(tvid=tvId, vid=vid)
for i in index: try:
vid = list[int(i) - 1][1] if response['data']['boss_ts']['code'] != 'A00000':
response = self.get_dash(tvid=tvId, vid=vid) print(f'获取m3u8失败\n')
try: print(response['data']['boss_ts']['msg'])
if response['data']['boss_ts']['code'] != 'A00000': continue
print(f'获取m3u8失败\n') except:
print(response['data']['boss_ts']['msg']) pass
continue data = response['data']
except: program = data['program']
pass if 'video' not in program:
data = response['data'] print("无视频")
program = data['program'] continue
if 'video' not in program: video = program['video']
print("无视频") '''
continue for a in video:
video = program['video'] try:
''' scrsz = a.get('scrsz', '')
for a in video: vsize = get_size(a['vsize'])
try: m3u8data = a['m3u8']
scrsz = a.get('scrsz', '') fr = str(a['fr'])
vsize = get_size(a['vsize']) name = name + "_" + scrsz + "_" + vsize + "_" + fr + 'fps'
m3u8data = a['m3u8'] name = name.replace(' ', '_')
fr = str(a['fr']) file = f"./chache/{name}.m3u8"
name = name + "_" + scrsz + "_" + vsize + "_" + fr + 'fps' savepath = f"./download/iqy/{ctitle}"
name = name.replace(' ', '_') with open(file, 'w') as f:
file = f"./chache/{name}.m3u8" f.write(m3u8data)
savepath = f"./download/iqy/{ctitle}" if m3u8data.startswith('{"payload"'):
with open(file, 'w') as f: m3u8data = json.loads(m3u8data)
f.write(m3u8data) init = m3u8data['payload']['wm_a']['audio_track1']['codec_init']
if m3u8data.startswith('{"payload"'): pssh = get_pssh(init)
m3u8data = json.loads(m3u8data) key_string = get_key(pssh)
init = m3u8data['payload']['wm_a']['audio_track1']['codec_init'] cmd = f"N_m3u8DL-RE.exe \"{file} \" --tmp-dir ./cache --save-name \"{name}\" --save-dir \"{savepath}\" --thread-count 16 --download-retry-count 30 --auto-select --check-segments-count " + key_string + " --decryption-binary-path ./mp4decrypt.exe -M format=mp4"
pssh = get_pssh(init) if m3u8data.startswith('<?xml'):
key_string = get_key(pssh) pssh = m3u8data.split('<cenc:pssh>')[1].split('</cenc:pssh>')[0]
cmd = f"N_m3u8DL-RE.exe \"{file} \" --tmp-dir ./cache --save-name \"{name}\" --save-dir \"{savepath}\" --thread-count 16 --download-retry-count 30 --auto-select --check-segments-count " + key_string + " --decryption-binary-path ./mp4decrypt.exe -M format=mp4" key_string = get_key(pssh)
else: cmd = f"N_m3u8DL-RE.exe \"{file} \" --tmp-dir ./cache --save-name \"{name}\" --save-dir \"{savepath}\" --thread-count 16 --download-retry-count 30 --auto-select --check-segments-count " + key_string + " --decryption-binary-path ./mp4decrypt.exe -M format=mp4"
cmd = f"N_m3u8DL-RE.exe \"{file} \" --tmp-dir ./cache --save-name \"{name}\" --save-dir \"{savepath}\" --thread-count 16 --download-retry-count 30 --auto-select --check-segments-count " else:
with open(f"{ctitle}.bat", 'a', encoding='gbk') as f: cmd = f"N_m3u8DL-RE.exe \"{file} \" --tmp-dir ./cache --save-name \"{name}\" --save-dir \"{savepath}\" --thread-count 16 --download-retry-count 30 --auto-select --check-segments-count "
f.write(cmd) with open(f"{ctitle}.bat", 'a', encoding='gbk') as f:
f.write("\n") f.write(cmd)
print(f"获取{name}成功") f.write("\n")
except: print(f"获取{name}成功")
continue except:
else: continue
continue else:
continue
if __name__ == '__main__':
ck = "" if __name__ == '__main__':
iq = iqy(ck) ck = ""
iq.run() iq = iqy(ck)
iq.run()

Loading…
Cancel
Save