Хочу поделиться небольшим скриптом, который делает для меня простую, но весьма полезную вещь — производит групповое переименование скачанных файлов так, что файлы получают удобно читаемое имя со страницы на сайте торрент трекера.
В итоге вместо "God.Bless.America.2011.HDTVRiP720.mkv"
я получаю файл с именем "Боже, Благослови Америку God Bless America (Боб Голдтуэйт Bobcat Goldthwait) (2011) США, триллер, чёрная комедия, криминал, HDTVRip-AVC.mkv"
В продолжение к теме Можно ли прибраться на компе раз и навсегда?
В общем вот что делает скрипт: производит поиск по каталогу Downloads, ищет скачанные файлы и соответствующие им .torrent файлы. Затем берет из .torrent файла URL странички на rutracker.org, загружает эту страничку и получает название закачки. Затем, на основании полученного текста, скрипт и переименовывает скачанный файл.
Для успешной работы скрипта понадобится Python 2.7 и uTorrent клиент с небольшой настройкой:
Prefferences -> Other -> Store .torrent files in:
Здесь необходимо указать каталог, куда uTorrent будет копировать .torrent файлы. Дел в том, что uTorrent, при копировании .torrent файлов в этот каталог, дает им такое-же имя как и скачиваемый файл. Чем я собственно и воспользовался.
В скрипте этот каталог необходимо указать как TORRENT_TORRENT_DIR.
Также необходимо прописать каталог, где скрипт будет искать и переименовывать скачанные файлы, см. переменную TORRENT_COMPLETED_DIR.
# coding=UTF-8
import os
import re
import urllib2
import shutil
TORRENT_COMPLETED_DIR = u'D:/Загрузки'
TORRENT_TORRENT_DIR = u'D:/Загрузки/uTorrent/torrent'
def Print(toPrint):
toPrint = unicode(toPrint)
toPrint = toPrint.encode('cp866', 'replace')
print toPrint
def GetTorrentFilePath(sFileName):
sFileName = unicode(sFileName)
sFilePath = os.path.join(TORRENT_TORRENT_DIR, sFileName + u'.torrent')
if not os.path.exists(sFilePath):
Print(u'Skiped, .torrent is not found: "%s' % sFilePath)
return None
return sFilePath
def GetTrackerUrl(sTorrentFilePath):
sTorrentFilePath = unicode(sTorrentFilePath)
try:
aTorrentFile = open(sTorrentFilePath, 'r')
sFileData = aTorrentFile.read()
sTrackerUrlLen, sTrackerUrl = re.search(r'comment([0-9]{2}):(.+)', sFileData).groups()
sTrackerUrl = re.search(r'(.{' + sTrackerUrlLen + '})', sTrackerUrl).groups()[0]
return sTrackerUrl
except:
Print(u"Error, can't extract tracker url from .torrent file %s" % sTorrentFilePath)
return None
def LoadTrackerPage(sTrackerUrl):
try:
response = urllib2.urlopen(sTrackerUrl)
sHtmlPage = response.read()
except:
Print(u"Error, Can't load tracker page '%s'" % sTrackerUrl)
return None
sHtmlPage = unicode(sHtmlPage, "cp1251")
return sHtmlPage
def PrepareFileName(sFileName):
sFileName = unicode(sFileName)
try:
#remove special symbols
sFileName = re.sub(ur'[\/:"*?<>|]+', '', sFileName, 0, re.UNICODE)
#remove repeating spaces
sFileName = re.sub(ur'[ ]+', ' ', sFileName, 0, re.UNICODE)
sFileName = sFileName.strip()
except:
Print(u"Error, can't prepare file name '%s'" % sFileName)
return None
return sFileName
class FileInfo:
pass
def ParseTrackerPage(sHtmlPage):
sHtmlPage = unicode(sHtmlPage)
try:
sPageTitle = re.search(r'<title>(.+?) :: .+?</title>', sHtmlPage, re.UNICODE).groups()[0]
except:
Print(u"Error, Can't parse <title>")
return None
file_info = FileInfo()
file_info.name = u""
file_info.year = u""
file_info.descr = u""
try:
file_info.name, file_info.year, file_info.descr = re.search(ur'(.+?) [([0-9]{4}).*?, (.+?)]', sPageTitle, re.UNICODE).groups()
except:
Print(u"Warning, Can't parse page title: %s" % sPageTitle)
try:
file_info.name, file_info.year, file_info.descr = re.search(ur'(.+?)([0-9]{4}).*?, (.+?)$', sPageTitle, re.UNICODE).groups()
except:
Print(u"Warning, Can't parse page title: %s" % sPageTitle)
file_info.name = sPageTitle
file_info.name = unicode(file_info.name)
file_info.year = unicode(file_info.year)
file_info.descr = unicode(file_info.descr)
return file_info
def GetDataFromTorrent(sFileName):
sTorrentFilePath = GetTorrentFilePath(sFileName)
if not sTorrentFilePath:
return None
sTrackerUrl = GetTrackerUrl(sTorrentFilePath)
if not sTrackerUrl:
return None
sHtmlPage = LoadTrackerPage(sTrackerUrl)
if not sHtmlPage:
return None
return ParseTrackerPage(sHtmlPage)
def PrepareNewFileName(fileName, file_info):
fileName = unicode(fileName)
tmp, ext = os.path.splitext(fileName)
toPrepare = file_info.name + u' (' + file_info.year + u') ' + file_info.descr
toPrepare = unicode(toPrepare)
cleanName = PrepareFileName(toPrepare)
newFileName = cleanName + ext
return newFileName
def main():
Print(u'Hello, Find downloads in "%s" :' % TORRENT_COMPLETED_DIR)
total = 0
renamed = 0
for sFileName in os.listdir(TORRENT_COMPLETED_DIR):
total = total + 1
unicode(sFileName)
Print(u'Process a file: "%s"' % sFileName)
file_info = GetDataFromTorrent(sFileName)
if file_info is None:
continue
sNewFileName = PrepareNewFileName(sFileName, file_info)
if sNewFileName:
sOldFilePath = unicode(os.path.join(TORRENT_COMPLETED_DIR, sFileName))
sNewFilePath = unicode(os.path.join(TORRENT_COMPLETED_DIR, sNewFileName))
try:
shutil.move(sOldFilePath, sNewFilePath)
renamed = renamed + 1
except:
Print(u"Error, Can't rename %s to %s" % (sOldFilePath, sNewFilePath))
Print(u"%d friles were renamed from %d total found files" % (renamed, total))
if __name__ == "__main__":
main()
Работа скрипта проверялась на Windows 7 x86 и Windows 7 x64
В теории скрипт может заработать под Linux, но у меня на этот счет есть сомнения.
Скрипт заточен под rutracker, но возможно будет работать и с другими сайтами.
По крайней мере после доработки напильником.
Для скачивания html странички я использовал библиотеку urllib2.
А для парсинга .torrent файлов и html я использовал регулярные выражения.
Оказалось, что на Python их использовать весьма удобно.
В принципи для парсинга html лучше было бы использовать css селекторы, но пока и так сойдет.
Конструкцию следующего типа
fileName = unicode(fileName)
я использовал для отладки, когда столкнулся с проблемой, когда создается не юникодная строчка с юникодными символоами и после этого программа начинает падать в непонятных местах. Эту проблему похоже исправили в Python 3.
Так как Python это не мой основной язык, то буду рад советам опытных разработчиков.
Автор: Ryadovoy