最近把家里的HDPC终于改成Debian了,起初一直在Windows 10下,但经过长时间的使用,装着E5200芯的老机器终于拉不动了,启动都要卡半天。思索了半天,干脆换到了Debian下。没去试现在的安卓X86版本和凤凰系统,是因为不想过于折腾了,虽说Debian并不是个好的娱乐平台,但好在安装Kodi倒是很方便对这个系统也比较熟悉,而我也仅仅用它就可以了。

安装的是Debian 9.4版本, Kodi是17.6的。设置什么的轻车熟路,电影、电视、直播啥的都基本没问题,但找遍了网上现有的中文字幕插件,就没一个可以用的,有的说是给15的版本可以用,但我没试而且也不想换版本。没办法了,只有自己改吧。

在这里真要吐槽一下Kodi的官方资料,英文的不说,而且是积极的简单,什么函数基本上就是一句话解释,连示例都没有一个,不过还好,综合了很多现成的源码,基本上了解了它字幕插件的思路和一些函数方法。代码是基于网络现有的插件基础上改的,字幕来源于字幕库。

首先是搜索函数,一番查验这个到是简单,原先的代码找不到内容是因为网站页面div的class改了,所以把bs的查找规则调整就ok了。

def Search( item ):    subtitles_list = []    log( __name__ ,"Search for [%s] by name" % (os.path.basename( item['file_original_path'] ),))    if item['mansearch']:        url = ZIMUKU_API % (item['mansearchstr'])    else:        url = ZIMUKU_API % (item['title'])    try:        socket = urllib.urlopen(url)        data = socket.read()        socket.close()        soup = BeautifulSoup(data,'html.parser')    except:        return    results = soup.find_all("div", class_="item prel clearfix")    for it in results:        moviename = it.find("div", class_="title").a.text.encode('utf-8')        iurl = it.find("div", class_="title").a.get('href').encode('utf-8')        movieurl = '%s%s' % (ZIMUKU_BASE, iurl)        try:            socket = urllib.urlopen(movieurl)            data = socket.read()            socket.close()            soup = BeautifulSoup(data,'html.parser').find("table", class_="table")            soup = soup.find("tbody")        except:            return        subs = soup.find_all("tr")        for sub in subs:            name = sub.a.text.encode('utf-8')            if name.split('.')[-1] not in ['zip','Zip','ZIP']: continue            flag = sub.img.get('src').split('/')[-1].split('.')[0].encode('utf-8')            lang = FLAG_DICT.get(flag,'unkonw')            link = '%s%s' % (ZIMUKU_BASE, sub.a.get('href').encode('utf-8'))            if lang == '英':                subtitles_list.append({"language_name":"English", "filename":name, "link":link, "language_flag":'en', "rating":"0", "lang":lang})            else:                subtitles_list.append({"language_name":"Chinese", "filename":name, "link":link, "language_flag":'zh', "rating":"0", "lang":lang})

而下载函数就麻烦了一点,看原来代码是获取下载地址后直接下载,而实际上我在网站下载时发现网站使用了301重定向,并且在访问下载地址时,网站做了防爬虫处理,需要在头里带上Referer,否则系统是不会给你正确的定向地址的,经过改动的代码如下:

def Download(url,lang):    try: shutil.rmtree(__temp__)    except: pass    try: os.makedirs(__temp__)    except: pass    exts = [".srt", ".sub", ".smi", ".ssa", ".ass" ]    try:        socket = urllib.urlopen( url )        data = socket.read()        soup = BeautifulSoup(data,'html.parser')        url = soup.find("li", class_="li dlsub").a.get('href').encode('utf-8')        socket = urllib.urlopen(url)        socket = urllib.urlopen(url)        data = socket.read()        soup = BeautifulSoup(data,'html.parser')        div = soup.find('div',class_='down clearfix')        li = div.find('li')        headers['Referer'] = url        req = urllib2.Request(li.a.get('href'),headers=headers)        resp = urllib2.urlopen(req)        socket = urllib.urlopen(resp.geturl())        data = socket.read()        socket.close()    except:        return []    if len(data) < 1024: return []    tempfile = os.path.join(__temp__, "subtitles.zip")    xbmc.log(tempfile)    with open(tempfile, "wb") as subFile: subFile.write(data)    subFile.close()    xbmc.sleep(500)    lists = unZip(tempfile)    lists = [i for i in lists if os.path.splitext(i)[1] in exts]    if len(lists) == 1:        return lists[0]    else:        index = [i.split('/')[-1] for i in lists]        sel = xbmcgui.Dialog().select('请选择压缩包中的字幕', index)        if sel == -1: sel = 0        return lists[sel]

经过调整,大的问题没有了,不过些小的地方,原代码里貌似是只能在Windows下用的,因为好像它是用Winrar来解压的,而我在Debian下使用,所以只能考虑Zip文件了,至于能不能用rar包还有单独的srt等文件,以后折腾吧。

def getFileList(path):    fileslist = []    for d in os.listdir(path):        if os.path.isdir(path+d):            fileslist.extend(getFileList(path+d+'/'))        if os.path.isfile(path+d):            fileslist.append(path+d)    return fileslistdef unZip(filepath):    zip_file = zipfile.ZipFile(filepath,'r')    for names in zip_file.namelist():        if type(names) == str and names[-1] != '/':            utf8name = names.decode('gbk')            data = zip_file.read(names)            fo = open(os.path.join(__temp__, utf8name), "w")            fo.write(data)            fo.close()        else:            zip_file.extract(names,__temp__)    return getFileList(__temp__+'/')

总结一下啊,用惯了Python3后用2真的不习惯,并且在Kodi里测试也是非常的不方便,改动一下需要重新进入才行,经过测试在Linux和Windows下都没问题,版本从17到最新的18,至于更低的版本则没测试,接下来要把各种字幕扩展名的文件下载功能补全,等到某一天有心情折腾了再说吧。附地址:https://pan.baidu.com/s/1GxAod4Xdll-3pvM_OOru8A

更新:由于上次改的有太多的局限性,所以继续抽时间改了改,现在这个版本继续支持Linux和Windows,并且文件格式由单纯的zip扩展到rar的压缩,还包括了各种未压缩的字幕格式,由于网上并没有发现7z的字幕压缩包,所以就没有考虑这个格式了。但现在由于格式的增多,就带来了一些问题,为了这个插件的正常使用,在Windows下必须要安装WinRAR并且目录还得是C:\Program Files\WinRAR,在Linux下需要安装unrar,否则的话会下载失败,其他没有要求,注意这点即可。

贴上代码:

def getFileList(path):    fileslist = []    for d in os.listdir(path):        if os.path.isdir(path+d):            fileslist.extend(getFileList(path+d+'/'))        if os.path.isfile(path+d):            fileslist.append(path+d)    return fileslistdef extractCompress(file):    path  = __temp__ + '/subtitles/'    if os.path.isdir(path): shutil.rmtree(path)    if not os.path.isdir(path): os.mkdir(path)    if file.lower().endswith('zip'):        zipFile = zipfile.ZipFile(file,'r')        for names in zipFile.namelist():            if type(names) == str and names[-1] != '/':                utf8name = names.decode('gbk')                data = zipFile.read(names)                with open(path+utf8name, 'wb') as f: f.write(data)            else:                zipFile.extract(names,path)        return getFileList(path)    if file.lower().endswith('rar'):        if platform.system() == 'Windows':            rarPath = 'C:\Program Files\WinRAR'            sysPath = os.getenv('Path')            if 'winrar' not in sysPath.lower(): os.environ["Path"] = sysPath+';'+rarPath            command = "winrar x -ibck %s %s" % (file, path)        if platform.system() == 'Linux':            command = 'unrar x %s %s' % (file, path)        res = os.system(command)        if res == 0: return getFileList(path)def Search( item ):    subtitles_list = []    log(__name__ ,"Search for [%s] by name" % os.path.basename(item['file_original_path']))    if item['mansearch']:        url = ZIMUKU_API % (item['mansearchstr'])    else:        url = ZIMUKU_API % (item['title'])    try:        socket = urllib.urlopen(url)        data = socket.read()        socket.close()        soup = BeautifulSoup(data,'html.parser')    except:        return    results = soup.find_all("div", class_="item prel clearfix")    for it in results:        moviename = it.find("div", class_="title").a.text.encode('utf-8')        iurl = it.find("div", class_="title").a.get('href').encode('utf-8')        movieurl = '%s%s' % (ZIMUKU_BASE, iurl)        try:            socket = urllib.urlopen(movieurl)            data = socket.read()            socket.close()            soup = BeautifulSoup(data,'html.parser').find("table", class_="table")            soup = soup.find("tbody")        except:            return        subs = soup.find_all("tr")        for sub in subs:            name = sub.a.text.encode('utf-8')            flag = sub.img.get('src').split('/')[-1].split('.')[0].encode('utf-8')           .get(flag,'unkonw')            link = '%s%s' % (ZIMUKU_BASE, sub.a.get('href').encode('utf-8'))            if lang == '英':                subtitles_list.append({"language_name":"English", "filename":name, "link":link, "language_flag":'en', "rating":"0", "lang":lang})            else:                subtitles_list.append({"language_name":"Chinese", "filename":name, "link":link, "language_flag":'zh', "rating":"0", "lang":lang})    if subtitles_list:        for it in subtitles_list:            listitem = xbmcgui.ListItem(label=it["language_name"],                                  label2=it["filename"],                                  iconImage=it["rating"],                                  thumbnailImage=it["language_flag"]                                  )            listitem.setProperty( "sync", "false" )            listitem.setProperty( "hearing_imp", "false" )            url = "plugin://%s/?action=download&link=%s&lang=%s" % (__scriptid__,                                                                        it["link"],                                                                        it["lang"]                                                                        )            xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=listitem,isFolder=False)def Download(url,lang):    try: shutil.rmtree(__temp__)    except: pass    try: os.makedirs(__temp__)    except: pass    exts = [".srt", ".sub", ".smi", ".ssa", ".ass" ]    try:        socket = urllib.urlopen( url )        data = socket.read()        soup = BeautifulSoup(data,'html.parser')        url = soup.find("li", class_="li dlsub").a.get('href').encode('utf-8')        socket = urllib.urlopen(url)        socket = urllib.urlopen(url)        data = socket.read()        soup = BeautifulSoup(data,'html.parser')        div = soup.find('div',class_='down clearfix')        li = div.find('li')        headers['Referer'] = url        req = urllib2.Request(li.a.get('href'),headers=headers)        resp = urllib2.urlopen(req)        fileName = resp.headers['Content-Disposition'].replace('"','').split('=')[1]        socket = urllib.urlopen(resp.geturl())        data = socket.read()        socket.close()    except:        return []    if len(data) < 1024: return []    tempfile = os.path.join(__temp__, "subtitles.%s" % fileName.split('.')[-1])    xbmc.log(tempfile)    with open(tempfile, "wb") as subFile: subFile.write(data)    xbmc.sleep(100)    if fileName.split('.')[-1].lower() in ('zip','rar'):        lists = extractCompress(tempfile)    else:        lists = [tempfile]    lists = [i for i in lists if os.path.splitext(i)[1] in exts]    if len(lists) == 1:        return lists[0]    else:        index = [i.split('/')[-1] for i in lists]        sel = xbmcgui.Dialog().select('请选择压缩包中的字幕', index)        if sel == -1: sel = 0        return lists[sel]

贴上下载地址:点击下载