我的第一个在 Boa Constructor 下写的 wxPython 程序…
基本功能:
1, 输入影片名(中文/英文, 可以不输全) 输出影片信息
2, 从资源管理器拖放mkv文件到窗口, 输出影片信息+文件信息(分辨率 片长 MD5/SHA1/ed2k链接 等等)
***ChangeLog***
20100514 0.11a
增加制作par2包功能
hash可选
卡界面的事情移到子线程,多线程操作
增加制作人选择功能
完美实现跨平台兼容(WinXP/Ubuntu x64已测试)
20100329 发布第一个版本(v0.1a)
下载请移步 http://code.google.com/p/movieinfofetch/downloads/list
以下是全部代码:
#Boa:Frame:Frame1
# -*- coding: utf-8 -*-
import wx
import wx.richtext
import urllib,hashlib
import re
from MediaInfoDLL import *
import time
import threading
import thread
import Queue
import traceback
import os
import sys
from xml.dom import minidom
reload(sys)
sys.setdefaultencoding('utf8')
store='' #FileInfo
store2='' #MovieInfo
store3='' #CustomInfo
authorname=[]
file=''
file2=''
addone = False
from wx.lib import newevent
def create(parent):
return Frame1(parent)
[wxID_FRAME1, wxID_FRAME1BUTTON1, wxID_FRAME1BUTTON2, wxID_FRAME1BUTTON3,
wxID_FRAME1BUTTON4, wxID_FRAME1CHECKBOX1, wxID_FRAME1COMBOBOX1,
wxID_FRAME1PANEL1, wxID_FRAME1RICHTEXTCTRL1, wxID_FRAME1STATICTEXT1,
wxID_FRAME1TEXTCTRL1,
] = [wx.NewId() for _init_ctrls in range(11)]
class MyFileDropTarget(wx.FileDropTarget):
def __init__(self, window):
wx.FileDropTarget.__init__(self)
self.window = window
def OnDropFiles(self, x, y, filenames):
global file
#self.window.AppendText("\n%d file(s) dropped at (%d,%d):\n" % (len(filenames), x, y))
self.window.Clear()
for file in filenames:
self.window.AppendText(file)
return
class Frame1(wx.Frame):
def _init_coll_flexGridSizer1_Items(self, parent):
# generated method, don't edit
parent.AddWindow(self.staticText1, 0, border=9,
flag=wx.ADJUST_MINSIZE | wx.ALL)
parent.AddWindow(self.textCtrl1, 0, border=5, flag=wx.EXPAND | wx.ALL)
parent.AddWindow(self.button1, 0, border=5,
flag=wx.ADJUST_MINSIZE | wx.ALL)
parent.AddWindow(self.comboBox1, 1, border=5, flag=wx.EXPAND | wx.ALL)
def _init_coll_flexGridSizer2_Items(self, parent):
# generated method, don't edit
parent.AddWindow(self.button2, 0, border=5,
flag=wx.ADJUST_MINSIZE | wx.ALL)
parent.AddWindow(self.button3, 0, border=5,
flag=wx.ADJUST_MINSIZE | wx.ALL)
parent.AddWindow(self.button4, 0, border=5,
flag=wx.ADJUST_MINSIZE | wx.ALL)
parent.AddWindow(self.checkBox1, 0, border=0, flag=0)
def _init_coll_boxSizer1_Items(self, parent):
# generated method, don't edit
parent.AddSizer(self.flexGridSizer1, 0, border=0, flag=0)
parent.AddWindow(self.richTextCtrl1, 1, border=7,
flag=wx.EXPAND | wx.ALL)
parent.AddSizer(self.flexGridSizer2, 0, border=0, flag=0)
def _init_sizers(self):
# generated method, don't edit
self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)
self.flexGridSizer1 = wx.FlexGridSizer(cols=0, hgap=0, rows=1, vgap=0)
self.flexGridSizer2 = wx.FlexGridSizer(cols=0, hgap=0, rows=1, vgap=0)
self._init_coll_boxSizer1_Items(self.boxSizer1)
self._init_coll_flexGridSizer1_Items(self.flexGridSizer1)
self._init_coll_flexGridSizer2_Items(self.flexGridSizer2)
self.panel1.SetSizer(self.boxSizer1)
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
pos=wx.Point(535, 138), size=wx.Size(467, 481),
style=wx.DEFAULT_FRAME_STYLE,
title='Movie Info Fetcher v0.11a - By Felix Yan')
self.SetClientSize(wx.Size(467, 481))
self.SetBackgroundColour(wx.Colour(222, 222, 222))
self.Bind(wx.EVT_CLOSE, self.OnFrame1Close)
self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
pos=wx.Point(0, 0), size=wx.Size(467, 481),
style=wx.TAB_TRAVERSAL)
self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
label='\xc6\xac\xc3\xfb'.decode('gbk'), name='staticText1',
parent=self.panel1, pos=wx.Point(9, 9), size=wx.Size(31, 13),
style=0)
self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1',
parent=self.panel1, pos=wx.Point(54, 5), size=wx.Size(146, 27),
style=0, value='')
self.button1 = wx.Button(id=wxID_FRAME1BUTTON1,
label='\xbc\xec\xcb\xf7\xd0\xc5\xcf\xa2'.decode('gbk'),
name='button1', parent=self.panel1, pos=wx.Point(210, 5),
size=wx.Size(75, 23), style=0)
self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
id=wxID_FRAME1BUTTON1)
self.button2 = wx.Button(id=wxID_FRAME1BUTTON2,
label=u'\u5236\u4f5cpar2\u5305', name='button2',
parent=self.panel1, pos=wx.Point(5, 453), size=wx.Size(120, 23),
style=0)
self.button2.Bind(wx.EVT_BUTTON, self.OnButton2Button,
id=wxID_FRAME1BUTTON2)
self.richTextCtrl1 = wx.richtext.RichTextCtrl(id=wxID_FRAME1RICHTEXTCTRL1,
parent=self.panel1, pos=wx.Point(7, 44), size=wx.Size(453, 397),
style=wx.richtext.RE_MULTILINE, value='')
self.button3 = wx.Button(id=wxID_FRAME1BUTTON3,
label='\xb8\xb4\xd6\xc6\xb5\xbd\xbc\xf4\xcc\xf9\xb0\xe5'.decode('gbk'),
name='button3', parent=self.panel1, pos=wx.Point(135, 453),
size=wx.Size(120, 23), style=0)
self.button3.Bind(wx.EVT_BUTTON, self.OnButton3Button,
id=wxID_FRAME1BUTTON3)
self.comboBox1 = wx.ComboBox(choices=[], id=wxID_FRAME1COMBOBOX1,
name='comboBox1', parent=self.panel1, pos=wx.Point(295, 5),
size=wx.Size(160, 27), style=0, value=u'')
self.comboBox1.SetLabel(u'')
self.comboBox1.Bind(wx.EVT_COMBOBOX, self.OnComboBox1Combobox,
id=wxID_FRAME1COMBOBOX1)
self.comboBox1.Bind(wx.EVT_TEXT, self.OnComboBox1Text,
id=wxID_FRAME1COMBOBOX1)
self.checkBox1 = wx.CheckBox(id=wxID_FRAME1CHECKBOX1,
label=u'\u8ba1\u7b97Hash', name='checkBox1', parent=self.panel1,
pos=wx.Point(385, 448), size=wx.Size(80, 23), style=0)
self.checkBox1.SetValue(True)
self.button4 = wx.Button(id=wxID_FRAME1BUTTON4,
label=u'\u4fdd\u5b58\u5230\u6587\u672c\u6587\u4ef6',
name='button4', parent=self.panel1, pos=wx.Point(265, 453),
size=wx.Size(115, 23), style=0)
self.button4.Bind(wx.EVT_BUTTON, self.OnButton4Button,
id=wxID_FRAME1BUTTON4)
self._init_sizers()
def __init__(self, parent):
self._init_ctrls(parent)
dt = MyFileDropTarget(self.textCtrl1)
self.richTextCtrl1.SetDropTarget(dt)
self.button1.SetDefault()
self.GetAuthorName()
def OnButton1Button(self, event):
global store
global store2
global authorname
if authorname.count(self.comboBox1.GetValue())>0:
authorname.remove(self.comboBox1.GetValue())
if self.comboBox1.GetValue()!= '':
authorname.insert(0,self.comboBox1.GetValue())
self.comboBox1.Clear()
self.comboBox1.AppendItems(authorname)
if len(authorname)>0:
self.comboBox1.SetValue(authorname[0])
store2=''
store=''
self.richTextCtrl1.Clear()
GetInfo(self, self.textCtrl1.GetValue())
def OnButton2Button(self, event):
self.progress3 = wx.ProgressDialog("Creating...", u"正在创建par2包, 请稍候…", 100, style=wx.PD_AUTO_HIDE)
self.t = TRun3(self)
self.t.setDaemon(True)
self.t.start()
#dlg = wx.TextEntryDialog(None, u"新字段名?",u'增加自定义字段', '')
#if dlg.ShowModal() == wx.ID_OK:
# response1 = dlg.GetValue()
# if len(response1)==3:
# response1=response1[0]+' '+response1[1]+' '+response1[2]
# else:
# if len(response1)==2:
# response1=response1[0]+u' '+response1[1]
#
# dlg2 = wx.TextEntryDialog(None, u"新字段内容?",u'增加自定义字段', '')
# if dlg2.ShowModal() == wx.ID_OK:
# response2 = dlg2.GetValue()
# self.richTextCtrl1.AppendText(u'◎'+response1+u' '+response2+'\n')
# dlg2.Destroy()
#dlg.Destroy()
#event.Skip()
def OnButton3Button(self, event):
setText(self.richTextCtrl1.GetValue())
event.Skip()
def GetAuthorName(self):
#xmlDom = minidom.Document()
global authorname
if not os.path.exists('authors.xml'): return
from xml.etree import ElementTree
root = ElementTree.parse(r"authors.xml")
lst_node = root.findall('name')
for node in lst_node:
nodename = node.text
authorname.append(nodename)
self.comboBox1.Append(nodename)
#for i in self.comboBox1.choices(): print i
if len(authorname)>0:
self.comboBox1.SetValue(authorname[0])
def onDone(self):
global store,store2
self.richTextCtrl1.Clear()
self.richTextCtrl1.AppendText(store2+'\n'+store)
def updateProgress1(self, i):
self.flag = self.progress.Update(i)
def updateProgress2(self, i):
self.flag = self.progress2.Update(i)
def updateProgress3(self, i):
self.flag = self.progress3.Update(i)
def destroyProgress1(self):
self.flag = self.progress.Destroy()
def destroyProgress2(self):
self.flag = self.progress2.Destroy()
def destroyProgress3(self):
self.flag = self.progress3.Destroy()
def OnComboBox1Combobox(self, event):
global authorname
authorname.remove(self.comboBox1.GetValue())
authorname.insert(0,self.comboBox1.GetValue())
def OnComboBox1Text(self, event):
global authorname
if not addone: return
if authorname.count(self.comboBox1.GetValue())>0:
authorname.remove(self.comboBox1.GetValue())
authorname.insert(0,self.comboBox1.GetValue())
self.comboBox1.Clear()
self.comboBox1.AppendItems(authorname)
def OnFrame1Close(self, event):
global authorname
impl = minidom.getDOMImplementation()
dom = impl.createDocument(None, 'authors', None)
root = dom.documentElement
for author in authorname:
item = dom.createElement('name')
text = dom.createTextNode(author)
item.appendChild(text)
root.appendChild(item)
#f = file('./authors.xml','w')
f = open('authors.xml','w')
#import codecs
#writer = codecs.lookup('utf-8')[3](f)
f.write(dom.toxml())
f.close()
exit()
def OnButton4Button(self, event):
content=self.richTextCtrl1.GetValue()
f=open('info.txt','w')
f.write(content.replace('\n','\r\n'))
f.close
wx.MessageBox(u'已成功保存到当前目录下的 info.txt 中!')
def look4(source,item,multi='',p=u':[\|\s()]*(.+?)',ml=1):
if multi!='':
r = re.compile(item+p+multi)
ms = r.findall(source)
if len(ms)>0:
ans=ms[0]
r=re.compile('([\|()]+|\s\s+|\s\||\|\s)')
ans=r.sub('|',ans)
while ans.find('||')>-1:
ans=ans.replace('||','|')
if cmp(ans[-1],'|')==0:
ans=ans[:-1]
if ml==1:
ans=ans.replace('|',u'\n ')
else:
ans=ans.replace('|',' / ')
else:
ans=''
else:
r = re.compile(item+p+'\|')
ms = r.findall(source)
if len(ms)>0:
ans=ms[0]
else:
ans=''
r = re.compile('\&\#.*?\;')
ans = r.sub('',ans)
return ans.strip()
def GetInfo(self, value):
global file,file2,store,store2
file=value
file2=value
store=''
store2=''
if (len(value)>0 and value[0]=='/') or (len(value)>3 and value[1:3]==':\\'):
self.progress = wx.ProgressDialog(u"Hashing...", u"正在计算文件Hash, 请稍候…", 100, style=wx.PD_AUTO_HIDE)
self.t = TRun(self)
self.t.setDaemon(True)
self.t.start()
#self.t.join()
time.sleep(0.5)
file2 = file.split("\\")[-1].split("/")[-1][0:25]
self.progress2 = wx.ProgressDialog(u"Searching...", u"正在获取影片信息, 请稍候…", 100, style=wx.PD_AUTO_HIDE)
self.t2 = TRun2(self)
self.t2.setDaemon(True)
self.t2.start()
else:
time.sleep(0.5)
self.progress2 = wx.ProgressDialog(u"Searching...", u"正在获取影片信息, 请稍候…", 100, style=wx.PD_AUTO_HIDE)
self.t2 = TRun2(self)
self.t2.setDaemon(True)
self.t2.start()
#while done<2:
# time.sleep(0.2)
def setText(aString):
if not wx.TheClipboard.IsOpened():
clipdata = wx.TextDataObject()
clipdata.SetText(aString)
wx.TheClipboard.Open()
wx.TheClipboard.SetData(clipdata)
wx.TheClipboard.Close()
pass
class BoaApp1(wx.App):
def OnInit(self):
self.main = create(None)
self.main.Show()
self.SetTopWindow(self.main)
return True
class TRun(threading.Thread):
def __init__(self, caller):
threading.Thread.__init__(self)
self.caller = caller
self.flag = True
def run(self):
global file
if self.caller.checkBox1.GetValue():
m1 = hashlib.md5()
m2 = hashlib.sha1()
md4 = hashlib.new('md4').copy
ed2k = []
filename = "\\".join(file.split("\\"))
f = open(filename,'rb')
f1 = os.stat(file)
size = f1.st_size
now = 9728000
bytes = f.read(9728000)
while(bytes != ''):
m1.update(bytes)
m2.update(bytes)
m3 = md4()
m3.update(bytes)
ed2k.append(m3.digest())
i=now*100/size
if(i>100): i=100
#self.caller.ThreadSafeDispatch(self.update, i)
wx.CallAfter(self.caller.updateProgress1, i)
bytes = f.read(9728000)
now+=9728000
f.close()
if len(ed2k)==1:
ed2kvalue = ed2k[0].encode("hex")
else:
m3 = md4()
m3.update(reduce(lambda a,d: a + d, ed2k, ""))
ed2kvalue = m3.hexdigest()
md5value = m1.hexdigest()
sha1value = m2.hexdigest()
global store,store2
MI = MediaInfo()
MI.Open(file)
#self.window.AppendText(file)
store = ''
#store2 = ''
store += u"◎文件名称 "+file.split("\\")[-1].split("/")[-1]+'\n'
store += u"◎文件大小 "+MI.Get(Stream.General, 0, u"FileSize/String4")+'\n'
store += u"◎影片长度 "+MI.Get(Stream.General, 0, u"Duration/String3")+'\n'
overallbitrate = MI.Get(Stream.General, 0, u"OverallBitRate/String")
store += u"◎混合码率 "+overallbitrate+'\n'
store += u"◎封装时间 "+MI.Get(Stream.General, 0, u"Encoded_Date")+'\n'
store += u"◎MMG 版本 "+MI.Get(Stream.General, 0, u"Encoded_Application")+'\n'
videobitrate = MI.Get(Stream.Video, 0, u"BitRate_Nominal/String")
if cmp(videobitrate,overallbitrate)!=0 and videobitrate!='':
store += u"◎视频码率 "+videobitrate+'\n'
audiobitrate = MI.Get(Stream.Audio, 0, u"BitRate_Nominal/String")
if cmp(audiobitrate,overallbitrate)!=0 and audiobitrate!='':
store += u"◎音频码率 "+audiobitrate+'\n'
store += u"◎视频尺寸 "+MI.Get(Stream.Video, 0, u"Width")+' x '+MI.Get(Stream.Video, 0, u"Height")+'\n'
store += u"◎画面比例 "+MI.Get(Stream.Video, 0, u"DisplayAspectRatio/String")+'\n'
store += u"◎帧 率 "+MI.Get(Stream.Video, 0, u"FrameRate/String")+'\n'
store += u"◎数据密度 "+MI.Get(Stream.Video, 0, u"Bits-(Pixel*Frame)")+'\n'
store += u"◎音轨信息 "+MI.Get(Stream.Audio, 0, u"Title")
for i in range(1,MI.Count_Get(Stream.Audio)):
store += " / "+MI.Get(Stream.Audio, i, u"Title")
store += "\n"
store += u"◎字幕信息 "+MI.Get(Stream.Text, 0, u"Title")
for i in range(1,MI.Count_Get(Stream.Text)):
store += " / "+MI.Get(Stream.Text, i, u"Title")
store += "\n"
store += u"◎片源采用 [b]"+MI.Get(Stream.Video, 0, u"Title")+'[/b]\n'
store += u"◎X264版本 "+MI.Get(Stream.Video, 0, u"Encoded_Library/Version")+'\n'
store += u"◎X264参数 "+MI.Get(Stream.Video, 0, u"Encoded_Library_Settings")+"\n\n"
if self.caller.checkBox1.GetValue():
store += u"◎检验MD5: "+md5value.upper()+'\n'
store += u"◎检验SHA1: "+sha1value.upper()+'\n'
#f = os.stat(file)
#size = f.st_size
store += u"\n[emule]ed2k://|file|"+file.split("\\")[-1].split("/")[-1]+"|"+"%d"%size+"|"+ed2kvalue.upper()+'|/[/emule]\n'
#store2 += "[b]"+'.'.join(file.split("\\")[-1].split('.')[:-1])+"[/b]\n"
#thread.start_new_thread(GetInfo,(self.caller,file.split("\\")[-1].split("/")[-1][0:25]))
#file = file.split("\\")[-1].split("/")[-1][0:25]
wx.CallAfter(self.caller.onDone)
wx.CallAfter(self.caller.destroyProgress1)
#for i in range(100):
# print 'run %d' % (i+1)
# self.caller.ThreadSafeDispatch(self.update, i)
# if not self.flag:
# self.destroy()
# #print 'flag', self.flag
# return
# time.sleep(0.1)
class TRun2(threading.Thread):
def __init__(self, caller):
threading.Thread.__init__(self)
self.caller = caller
self.flag = True
def run(self):
global file2
global store
global store2
global authorname
store2 = ''
imdb = file2
r = re.compile('tt\d{5,}')
ms = r.findall(imdb)
goon = 1
if len(ms)>0:
imdb = ms[0]
wx.CallAfter(self.caller.updateProgress2, 50)
goon = 0
if goon and imdb[0:4]=='http':
webdata = urllib.urlopen(imdb).read()
r=re.compile('tt\d{5,}')
ms = r.findall(webdata)
if len(ms)>0:
imdb = ms[0]
wx.CallAfter(self.caller.updateProgress2, 50)
goon = 0
if goon:
key=imdb.replace(" ","+")
key=urllib.quote(key.encode('utf-8'))
wx.CallAfter(self.caller.updateProgress2, 20)
#wx.MessageBox(key)
#webdata = unicode(urllib.urlopen("http://www.verycd.com/search/folders/"+key).read(),'utf-8')
#r=re.compile('http://www\.verycd\.com/topics/\d+')
webdata = unicode(urllib.urlopen("http://movie.douban.com/subject_search?search_text="+key+"&cat=1002").read(),'utf-8')
r=re.compile("http://movie\.douban\.com/subject/\d+")
ms = r.findall(webdata)
if len(ms)>0:
webdata = unicode(urllib.urlopen(ms[0]).read(),'utf-8')
r=re.compile('tt\d{5,}')
ms = r.findall(webdata)
if len(ms)>0:
imdb = ms[0]
wx.CallAfter(self.caller.updateProgress2, 50)
goon = 0
store2 += u'◎制 作 '
if len(authorname)>0:
store2 += authorname[0]
if not goon:
webdata = unicode(urllib.urlopen("http://www.7176.com/title/"+imdb).read(), 'gbk')
webdata = webdata.replace('\n','')
r = re.compile('\<.+?\>')
webdata = r.sub('\r',webdata)
webdata = webdata.replace('\r','|')
#webdata = webdata.replace('\n\r','\r')
name=look4(webdata,u'中文名')
engname=look4(webdata,u'外文别名')
#wx.MessageBox('|'+engname+'|')
if engname=='':
engname=look4(webdata,u'片.*?名')
else:
r=re.compile('\(.*?\)')
engname=r.sub('',engname).strip()
store2 += u'◎英 文 名 '+engname+'\n'
store2 += u'◎中 文 名 '+name+'\n'
store2 += u'◎导 演 '+look4(webdata,u'导.*?演')+'\n'
store2 += u'◎主 演 '+look4(webdata,u'主.*?演',u'上.*?映')+'\n'
store2 += u'◎年 代 '+look4(webdata,u'上.*?映')+'\n'
store2 += u'◎国 家 '+look4(webdata,u'地.*?区')+'\n'
store2 += u'◎语 言 '+look4(webdata,u'对.*?白')+'\n'
store2 += u'◎IMDb评分 '+look4(webdata,u'IMDb评分',p='[\|\s()]*(\d\.\d.*?)')+'\n'
store2 += u'◎IMDb链接 http://www.imdb.com/title/'+imdb+'/\n'
store2 += u'◎片 长 '+look4(webdata,u'时.*?长',p=':[\|\s()]*(\d+).*?')+' mins\n'
store2 += u'◎类 别 '+look4(webdata,u'类.*?型',multi=u'分.*?级',ml=0)+'\n'
wx.CallAfter(self.caller.updateProgress2, 100)
if not goon:
#wx.MessageBox(u'·'+name.replace('(','\(').replace(')','\)')+u'海报:')
jianjie=look4(webdata,u'·剧情介绍',u'·'+name.replace('(','\(').replace(')','\)')+u'海报:','[\|\s()]*(.+?)')
jianjie=jianjie.replace(' ',' ')
jianjie=jianjie.replace(u' ',' ')
while jianjie.find(' ')>-1:
jianjie=jianjie.replace(' ',' ')
jianjie=jianjie.replace('\n ','\n')
jianjie=jianjie.replace(' \n','\n')
jianjie=jianjie.replace('\r','')
jianjie=jianjie.replace('\n\n','\n')
jianjie=jianjie.replace('\n','
')
jianjie=jianjie.replace('
',u"\n\n ")
if jianjie!='':
if jianjie[0]==' ': jianjie = jianjie[1:]
jianjie=u' '+jianjie
store2 += u'\n◎简 介 \n'+jianjie+'\n'
wx.CallAfter(self.caller.onDone)
#self.caller.t.join()
#while(self.caller.t.isAlive()): self.caller.t.join()
#if store!='': self.caller.richTextCtrl1.AppendText('\n'+store)
#if store2!='': self.caller.richTextCtrl1.AppendText('\n'+store2)
#self.AppendText(webdata)
#d:ffmpeg\ffmpeg -map 0:2 -i a.mkv -f wav -ac 2 - | d:sox\sox --ignore-length --norm - -2 -t wav - | d:neroaacenc\neroAacEnc.exe -ignorelength -q 0.25 -if - -of v:\a.aac
wx.CallAfter(self.caller.destroyProgress2)
class TRun3(threading.Thread):
def __init__(self, caller):
threading.Thread.__init__(self)
self.caller = caller
self.flag = True
def run(self):
global file
#store=''
#store2=''
ans=''
if file=='': return
arg='par2 c -r3 \"'+file.encode(sys.getfilesystemencoding())+'.par2\" \"'+file.encode(sys.getfilesystemencoding())+'\"'
import subprocess
p = subprocess.Popen(args=arg,stdout=subprocess.PIPE, shell=True)
r1 = re.compile('Constructing[:\s]*([\d\.]+)%')
r2 = re.compile('Processing[:\s]*([\d\.]+)%')
r1yes = False
while p.poll()==None:
ans+=p.stdout.read(100)
if not r1yes:
k = r1.findall(ans)
k2 = r2.findall(ans)
if len(k2)>0:
r1yes = True
time.sleep(0.3)
else:
k = r2.findall(ans)
if len(k)>0:
#store = k[-1]
#store=ans
wx.CallAfter(self.caller.updateProgress3, int(float(k[-1])))
time.sleep(0.01)
ans=''
arg='7za a \"'+file.encode(sys.getfilesystemencoding())+'.par2.7z\" \"'+file.encode(sys.getfilesystemencoding())+'*par2\"'
#global store
p = subprocess.Popen(args=arg, stdout=subprocess.PIPE, shell=True)
p.wait()
time.sleep(0.3)
#file.split("\\")
if cmp(sys.platform[:3],'win')==0:
arg='del '+file.encode(sys.getfilesystemencoding())+'*par2'
else:
arg='rm -f '+file.encode(sys.getfilesystemencoding())+'*par2'
p = subprocess.Popen(args=arg, stdout=subprocess.PIPE, shell=True)
p.wait()
wx.CallAfter(self.caller.destroyProgress3)
def main():
application = BoaApp1(0)
application.MainLoop()
if __name__ == '__main__':
main()
到了http://code.google.com/p/movieinfofetch/downloads/list,下载哪一个文件呢?
I could remark Work and struggle and never accept an evil that you can change. or potentially Each problem that I solved became a rule which served afterwards to solve other problems.
哦,可以显示的,就是有些慢了,为什么一定要mkv格式呢,不知博主能否解释下~还有就是能不能再显示影片的图片啊,就像豆瓣网的条目一样都有个缩略图的
1, 图片是可以提取的 只是我现在还没想好设计一个怎样的UI显示。。
2, 信息提取我是用的mediainfo插件,理论上它支持的应该都可以吧。。
其实再提取个影片介绍也不错啊,可以到豆瓣或时光网或者别的地方提取,期待更新啊~
影片介绍现在是从imdb中文那个网页直接提取的,如果再增加提取点肯定会造成提取时间变长。。。我可能会考虑做一个列表供选:)
对,有人需要有人不需要嘛~
“从资源管理器拖放mkv文件到窗口”,为什么一拖就未响应呢?
这个是在计算MD5等文件信息:)
牛,但我竟然不知道哪里用的 – –
对影视发布组很有用的:)
很久没见你更新了,这个要支持
谢谢支持:)
围观
青蛙你怎么这么快…
我在刷推。。。
你看看你代码。。。等号两边都没有空格的。。。
=.=有些有 我不习惯加空格…现在在努力习惯…