影片信息提取 —— 我的第一个wxPython程序

我的第一个在 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()

19 thoughts on “影片信息提取 —— 我的第一个wxPython程序”

  1. 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.

  2. 哦,可以显示的,就是有些慢了,为什么一定要mkv格式呢,不知博主能否解释下~还有就是能不能再显示影片的图片啊,就像豆瓣网的条目一样都有个缩略图的

    1. 1, 图片是可以提取的 只是我现在还没想好设计一个怎样的UI显示。。
      2, 信息提取我是用的mediainfo插件,理论上它支持的应该都可以吧。。

      1. 其实再提取个影片介绍也不错啊,可以到豆瓣或时光网或者别的地方提取,期待更新啊~

        1. 影片介绍现在是从imdb中文那个网页直接提取的,如果再增加提取点肯定会造成提取时间变长。。。我可能会考虑做一个列表供选:)

Leave a Reply

Your email address will not be published. Required fields are marked *

QR Code Business Card