[Python] 纯文本查看 复制代码
from tkinter import *
import tkinter.messagebox as messagebox
import requests
import json
import pyperclip
import re
"""人人影视下载资源解析"""
def WriteDict(dicts,txt="a.txt"):
"""
debug用的打印字典到文本文档
"""
with open(txt,'w') as fout:
for k,v in dicts.items():
fout.write(str(k)+':'+str(v)+'\n')
class YYets:
def __init__(self, master):
self.master = master
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0'}
self.api_search = 'http://pc.zmzapi.com/index.php?g=api/pv3&m=index&client=5&accesskey=519f9cab85c8059d17544947k361a827&a=search&uid=&token=&page=1&limit=30&k='
self.api_get = 'http://pc.zmzapi.com/index.php?g=api/pv3&m=index&client=5&accesskey=519f9cab85c8059d17544947k361a827&a=resource&uid=undefined&token=undefined&id='
self.listboxes = {}
self.initWidgets()
def initWidgets(self):
"""
初始化GUI布局
"""
#影剧搜索框、影剧搜索结果提示
frame = Frame(self.master)
frame.pack(expand=True, fill=BOTH, padx=10, pady=10, side=TOP)
self.entry = Entry(frame, width=30, font=('simkai', 12), foreground='red')
self.entry.pack(expand=True, fill=X, padx=0, pady=0, side=LEFT)
self.entry.bind('<Return>', self.searchDrama)
self.entry.insert(0, '关键词')
self.entry.selection_range(0, END)
self.entry.focus_set()
self.sr = StringVar()#这一变量变化时便可在GUI上立即显示
Label(frame, textvariable=self.sr, background='green', foreground='white', font=('simkai', 12), width=16, justify=CENTER).pack(expand=True, fill=X, padx=30, pady=0, side=LEFT)
#影剧搜索详细结果
frame = Frame(self.master)
frame.pack(expand=True, fill=BOTH, padx=10, pady=0, side=TOP)
self.srlist = StringVar()
listbox = Listbox(frame, listvariable=self.srlist, background='lightgreen', font=('simkai', 12), exportselection=False)
listbox.bind('<Double-Button-1>', self.chooseDrama)
listbox.bind('<Return>', self.chooseDrama)
#y滚动条
scrollbar = Scrollbar(frame)
scrollbar.pack(fill=Y, padx=0, pady=0, side=RIGHT)
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
#x滚动条
scrollbar = Scrollbar(frame, orient=HORIZONTAL)
scrollbar.pack(fill=X, padx=0, pady=0, side=BOTTOM)
listbox.config(xscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.xview)
listbox.pack(expand=True, fill=BOTH, padx=0, pady=0, side=LEFT)
self.listboxes['drama'] = listbox
#影剧季集title
self.videotitle = StringVar()
Label(self.master, textvariable=self.videotitle, background='green', foreground='white', font=('simkai', 12), justify=CENTER).pack(expand=True, fill=X, padx=10, pady=10, side=TOP)
#季、集、资源选择
topframe = Frame(self.master)
topframe.pack(expand=True, fill=BOTH, padx=10, pady=0, side=TOP)
#季
frame = Frame(topframe)
frame.pack(expand=True, fill=BOTH, padx=0, pady=0, side=LEFT)
self.seasonlist = StringVar()
listbox = Listbox(frame, listvariable=self.seasonlist, background='lightgreen', font=('simkai', 10), width=10, exportselection=False)
listbox.pack(expand=True, fill=BOTH, padx=0, pady=0, side=LEFT)
listbox.bind('<Double-Button-1>', self.chooseSeason)
listbox.bind('<Return>', self.chooseSeason)
scrollbar = Scrollbar(frame)
scrollbar.pack(fill=Y, padx=0, pady=0, side=RIGHT)
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
self.listboxes['season'] = listbox
#集
frame = Frame(topframe)
frame.pack(expand=True, fill=BOTH, padx=10, pady=0, side=LEFT)
self.episodelist = StringVar()
listbox = Listbox(frame, listvariable=self.episodelist, background='lightgreen', font=('simkai', 10), width=10, exportselection=False)
listbox.pack(expand=True, fill=BOTH, padx=0, pady=0, side=LEFT)
listbox.bind('<Double-Button-1>', self.chooseEpisode)
listbox.bind('<Return>', self.chooseEpisode)
scrollbar = Scrollbar(frame)
scrollbar.pack(fill=Y, padx=0, pady=0, side=RIGHT)
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
self.listboxes['episode'] = listbox
#资源
frame = Frame(topframe)
frame.pack(expand=True, fill=BOTH, padx=0, pady=0, side=LEFT)
self.srclist = StringVar()
listbox = Listbox(frame, listvariable=self.srclist, background='lightgreen', font=('simkai', 10), width=50, height=14, exportselection=False)
listbox.bind('<Double-Button-1>', self.copySrc)
listbox.bind('<Return>', self.copySrc)
scrollbar = Scrollbar(frame)
scrollbar.pack(fill=Y, padx=0, pady=0, side=RIGHT)
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
scrollbar = Scrollbar(frame, orient=HORIZONTAL)
scrollbar.pack(fill=X, padx=0, pady=0, side=BOTTOM)
listbox.config(xscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.xview)
listbox.pack(expand=True, fill=BOTH, padx=0, pady=0, side=LEFT)
self.listboxes['src'] = listbox
#空白
frame = Frame(self.master)
frame.pack(expand=True, fill=BOTH, padx=10, pady=5, side=BOTTOM)
def InitVariables(self):
"""
每次搜索影视剧均要重新初始化变量
"""
self.sr.set('')
self.srlist.set('')
self.videotitle.set('')
self.seasonlist.set('')
self.episodelist.set('')
self.srclist.set('')
self.idx = []
def searchDrama(self, event):
"""
搜索影视剧
"""
if self.entry.get() == '':
messagebox.showwarning(sys._getframe().f_code.co_name, '关键词缺失')
else:
self.InitVariables()
try:
response = requests.get(self.api_search+self.entry.get(), headers=self.headers)
if response.status_code != 200:
response.raise_for_status()
except Exception as e:
messagebox.showwarning('影视', e)
else:
#获取所有的结果
result = json.loads(response.text)
#生成结果list
self.ids = list(map(lambda i: result['data'][i]['id'], range(len(result['data']))))
self.ReqSources()
self.sr.set('查询结果:%d项' % len(result['data']))
self.srlist.set(list(map(lambda i: '%d.[%s].%s (%s),%s' % (i, result['data'][i]['channel_cn'], result['data'][i]['cnname'], result['data'][i]['enname'],self.dates[i]), range(len(result['data'])))))
#如果列表中只有一项,则自动选中
if self.listboxes['drama'].size() == 1:
self.listboxes['drama'].selection_set(0)
self.chooseDrama()
def ReqSources(self):
"""
获取所有搜索结果的页面
"""
sources = {}
dates = {}
for idx,drama_id in enumerate(self.ids):
try:
response_drama = requests.get(self.api_get+str(drama_id), headers=self.headers)
if response_drama.status_code != 200:
response_drama.raise_for_status()
except Exception as e:
messagebox.showwarning(sys._getframe().f_code.co_name, e)
else:
#获取该影视剧的页面
result_drama = json.loads(response_drama.text)
sources[idx]=result_drama
#获取该影视剧的年份
if result_drama['info'] in ['暂无资源', '资源关闭']:
dates[idx]=result_drama['info']
else:
try:
date=result_drama['data']['detail']['premiere']
except Exception as e:
messagebox.showwarning(sys._getframe().f_code.co_name, e)
else:
result = re.match(r'\d\d\d\d',date)
if result:
dates[idx]=result.group()
else:
dates[idx]=''
self.sources = sources
self.dates = dates
def chooseDrama(self, event='<Double-Button-1>'):
"""
选择影视剧后读取页面,并打印季数
"""
try:
drama_chosen = self.listboxes['drama'].get(self.listboxes['drama'].curselection())
except:
messagebox.showwarning(sys._getframe().f_code.co_name, '未选择影剧')
else:
self.seasonlist.set('')
self.episodelist.set('')
self.srclist.set('')
dramma_idx = int(drama_chosen[:drama_chosen.index('.')])
self.drama = drama_chosen[drama_chosen.index('.')+1:]
self.videotitle.set(self.drama)
result_drama = self.sources[dramma_idx]
self.parseDrama(result_drama)
def parseDrama(self, result_drama):
"""
解析该影视剧,并将影视剧的信息放入列表中
"""
if result_drama['info'] in ['暂无资源', '资源关闭']:
messagebox.showwarning(sys._getframe().f_code.co_name, result_drama['info'])
return
season_names = []
self.season_episodes = {}
self.src = {}
try:
for dics in result_drama['data']['list']:
episode_names = [] #对每季均要初始化episode_names
episodes = dics['episodes']
if episodes:
#正常情况,episodes是一个列表
#特殊情况,"episodes": null,则跳过
season_name = dics['season_name']
season_names.append(season_name)
for j in range(len(episodes)):
episode_name = episodes[j]['episode_name']
episode_names.append(episode_name)
self.src[season_name+episode_name] = []
files = episodes[j]['files']
for fileformat in files:
#yyets使用客户端就可以了,因此没必要显示yyets的链接
if fileformat != 'yyets':
for filesrc in files[fileformat]:
way_name = filesrc['way_name']
way_name = '[%s]:'%way_name
src_address = filesrc['address']
src_passwd = filesrc['passwd']
if src_passwd:
self.src[season_name+episode_name].append(way_name+src_address + ' pw: ' + src_passwd)
else:
self.src[season_name+episode_name].append(way_name+src_address)
self.season_episodes[season_name] = episode_names
self.seasonlist.set(season_names)
#如果列表中只有一项,则自动选中
if self.listboxes['season'].size() == 1:
self.listboxes['season'].selection_set(0)
self.chooseSeason()
except Exception as e:
messagebox.showwarning(sys._getframe().f_code.co_name, e)
def chooseSeason(self, event='<Double-Button-1>'):
"""
选择季后打印集数
"""
try:
#这里,不应该用self.listboxes['season'].get(ACTIVE)语句,
# 是因为在搜索上一个影视剧时该ACTIVE数值会被改掉,
# 而在搜索下一个影视剧时可能仅有1季,会在未经过双击时自动触发chooseSeason.
self.season_chosen = self.listboxes['season'].get(self.listboxes['season'].curselection())
except:
messagebox.showwarning(sys._getframe().f_code.co_name, '未选择“季”')
else:
self.episodelist.set('')
self.srclist.set('')
self.videotitle.set(self.drama + '.' + self.season_chosen)
self.episodelist.set(self.season_episodes[self.season_chosen])
#如果列表中只有一项,则自动选中
if self.listboxes['episode'].size() == 1:
self.listboxes['episode'].selection_set(0)
self.chooseEpisode()
def chooseEpisode(self, event='<Double-Button-1>'):
"""
选择集数后打印下载链接
"""
try:
episode_chosen = self.listboxes['episode'].get(self.listboxes['episode'].curselection())
except:
messagebox.showwarning(sys._getframe().f_code.co_name, '未选择“集”')
else:
self.srclist.set('')
self.videotitle.set(self.drama + '.' + self.season_chosen + '.' + episode_chosen)
if self.src[self.season_chosen+episode_chosen]:
self.srclist.set(self.src[self.season_chosen+episode_chosen])
else:
self.srclist.set('未发现下载资源')
def copySrc(self, event='<Double-Button-1>'):
"""
拷贝下载链接到剪贴板
"""
try:
src_chosen = self.listboxes['src'].get(self.listboxes['src'].curselection())
except:
messagebox.showwarning(sys._getframe().f_code.co_name, '未选择资源')
else:
#下载链接去掉way_name
if src_chosen=='未发现下载资源':
messagebox.showwarning(sys._getframe().f_code.co_name, '未发现下载资源')
else:
re_match = re.match(r'\[.*?\]:(.*)',src_chosen)
downlink = re_match.group(1)
#拷贝到剪贴板
pyperclip.copy(downlink)
messagebox.showinfo(sys._getframe().f_code.co_name, '%s\n\n已复制至剪贴板' % downlink)
if __name__ == '__main__':
root = Tk()
root.resizable(width=False, height=False)
root.title('人人影视下载资源解析')
YYets(root)
root.update_idletasks()
width, height = (root.winfo_width(), root.winfo_height())
screenwidth, screenheight = (root.winfo_screenwidth(), root.winfo_screenheight())
size_loc = '%dx%d+%d+%d' % (width, height, (screenwidth-width)/2, (screenheight-height)/2-30)
root.geometry(size_loc)
root.mainloop()