Хочу поделиться небольшим скриптом, который делает для меня простую, но весьма полезную вещь — производит групповое переименование скачанных файлов так, что файлы получают удобно читаемое имя со страницы на сайте торрент трекера.
В итоге вместо
В продолжение к теме Можно ли прибраться на компе раз и навсегда?
В общем вот что делает скрипт: производит поиск по каталогу Downloads, ищет скачанные файлы и соответствующие им .torrent файлы. Затем берет из .torrent файла URL странички на rutracker.org, загружает эту страничку и получает название закачки. Затем, на основании полученного текста, скрипт и переименовывает скачанный файл (вместо переименования можно выбрать копирование файлов в другой каталог, перенос или создание ссылок).
Для успешной работы скрипта понадобится Python 3 и uTorrent клиент с небольшой настройкой:
Prefferences -> Other -> Store .torrent files in:
Здесь необходимо указать каталог, куда uTorrent будет копировать .torrent файлы. Дел в том, что uTorrent, при копировании .torrent файлов в этот каталог, дает им такое-же имя как и скачиваемый файл. Чем я собственно и воспользовался.
В скрипте этот каталог необходимо указать как TORRENT_DIR.
Также необходимо прописать каталог, где скрипт будет искать скачанные файлы INPUT_DIR.
И каталог, куда скрипт будет копировать файлы (переносить или создавать жесткие ссылки), то есть OUTPUT_DIR.
При помощи переменной MOVE_ALGORITHM можно указать один из алгоритмов переноса файлов:
Работа скрипта проверялась на Windows 7 x86 и Windows 7 x64
В теории скрипт можно портировать и под Linux.
Скрипт заточен под rutracker, но возможно будет работать и с другими сайтами.
По крайней мере после доработки напильником.
Для скачивания html странички я использовал библиотеку urllib2.
А для парсинга .torrent файлов и html я использовал регулярные выражения.
Оказалось, что на Python их использовать весьма удобно.
В принципи для парсинга html лучше было бы использовать css селекторы, но пока и так сойдет.
Так как Python это не мой основной язык, то буду рад советам опытных разработчиков.
Update1:
На случай, если пример с файлом
Как по мне, то глаза и голову можно сломать пока поймешь что за фильм скрывается за одним из этих названий.
И естественно программы-каталогизаторы, наподобие AllMyMovies или Movienizer, не смогут в автоматическом режиме найти информацию об этих файлах в базах IMDB и Кинопоиск.
Update2:
По предложениям в комментариях решил обновить скрипт:
В итоге вместо
"God.Bless.America.2011.HDTVRiP720.mkv"
я получаю файл с именем "Боже, Благослови Америку God Bless America (Боб Голдтуэйт Bobcat Goldthwait) (2011) США, триллер, чёрная комедия, криминал, HDTVRip-AVC.mkv"
В продолжение к теме Можно ли прибраться на компе раз и навсегда?
В общем вот что делает скрипт: производит поиск по каталогу Downloads, ищет скачанные файлы и соответствующие им .torrent файлы. Затем берет из .torrent файла URL странички на rutracker.org, загружает эту страничку и получает название закачки. Затем, на основании полученного текста, скрипт и переименовывает скачанный файл (вместо переименования можно выбрать копирование файлов в другой каталог, перенос или создание ссылок).
Для успешной работы скрипта понадобится Python 3 и uTorrent клиент с небольшой настройкой:
Prefferences -> Other -> Store .torrent files in:
Здесь необходимо указать каталог, куда uTorrent будет копировать .torrent файлы. Дел в том, что uTorrent, при копировании .torrent файлов в этот каталог, дает им такое-же имя как и скачиваемый файл. Чем я собственно и воспользовался.
В скрипте этот каталог необходимо указать как TORRENT_DIR.
Также необходимо прописать каталог, где скрипт будет искать скачанные файлы INPUT_DIR.
И каталог, куда скрипт будет копировать файлы (переносить или создавать жесткие ссылки), то есть OUTPUT_DIR.
При помощи переменной MOVE_ALGORITHM можно указать один из алгоритмов переноса файлов:
- 'link' — создавать жесткие ссылки на файлы. Работает только для файловой системы NTFS в пределах одного диска. После создания жесткой ссылки, файл будет существовать до тех пор, пока не удалится последняя ссылка. По сути жесткая ссылка NTFS — это еще одно имя файла, равноценное с исходным
- 'copy' — скопировать файлы
- 'move' — перенести файлы из каталога INPUT_DIR в каталог OUTPUT_DIR. При выборе этого варианта будьте бдительны с активными закачками, если INPUT_DIR указывает на каталог, где производится раздача файлов
- 'move' в сочетании, когда INPUT_DIR == OUTPUT_DIR, производит переименование файлов на месте
# -*- encoding: utf-8 -*-
import os
import re
import urllib.request
import shutil
import sys
import ctypes
INPUT_DIR = 'D:/Downloads/uTorrent/Completed'
OUTPUT_DIR = 'D:/Video/Movies'
TORRENT_DIR = 'D:/Downloads/uTorrent/torrent'
MOVE_ALGORITHM = 'link'
def GetMoveAlgorithms():
return {'move' : MoveFile,
'copy' : CopyFile,
'link' : CreateHardLink}
def Print(msg):
msg = msg.encode('cp866', 'replace')
msg = msg.decode('cp866')
print(msg)
def GetTorrentFilePath(fileName):
filePath = os.path.join(TORRENT_DIR, fileName + '.torrent')
if not os.path.exists(filePath):
Print('Skiped, .torrent is not found: "%s' % filePath)
return None
return filePath
def GetTrackerUrl(torrentFilePath):
try:
torrentFile = open(torrentFilePath, 'r', encoding='ascii', errors='replace')
fileData = torrentFile.read()
trackerUrlLen, trackerUrl = re.search(r'comment([0-9]{2}):(.+)', fileData).groups()
trackerUrl = re.search(r'(.{' + trackerUrlLen + '})', trackerUrl).groups()[0]
return trackerUrl
except:
Print("Error, can't extract tracker url from .torrent file %s" % torrentFilePath)
return None
def LoadTrackerPage(trackerUrl):
try:
response = urllib.request.urlopen(trackerUrl)
htmlPage = response.read()
except:
Print("Error, Can't load tracker page '%s'" % trackerUrl)
return None
htmlPage = htmlPage.decode('cp1251')
return htmlPage
def PrepareFileName(fileName):
try:
#remove special symbols
fileName = re.sub(r'[\\/:"\*?<>|]+', '', fileName, 0, re.UNICODE)
#remove repeating spaces
fileName = re.sub(r'[ ]+', ' ', fileName, 0, re.UNICODE)
fileName = fileName.strip()
except:
Print("Error, can't prepare file name '%s'" % fileName)
return None
return fileName
class FileInfo:
pass
def ParseTrackerPage(htmlPage):
try:
pageTitle = re.search(r'<title>(.+?) :: .+?</title>', htmlPage, re.UNICODE).groups()[0]
except:
Print("Error, Can't parse <title>")
return None
fileInfo = FileInfo()
fileInfo.name = ""
fileInfo.year = ""
fileInfo.descr = ""
try:
fileInfo.name, fileInfo.year, fileInfo.descr = re.search(r'(.+?) \[([0-9]{4}).*?, (.+?)\]', pageTitle, re.UNICODE).groups()
except:
Print("Warning, Can't parse page title: %s" % pageTitle)
try:
fileInfo.name, fileInfo.year, fileInfo.descr = re.search(r'(.+?)([0-9]{4}).*?, (.+?)$', pageTitle, re.UNICODE).groups()
except:
Print("Warning, Can't parse page title: %s" % pageTitle)
fileInfo.name = pageTitle
return fileInfo
def GetDataFromTorrent(fileName):
torrentFilePath = GetTorrentFilePath(fileName)
if not torrentFilePath:
return None
trackerUrl = GetTrackerUrl(torrentFilePath)
if not trackerUrl:
return None
htmlPage = LoadTrackerPage(trackerUrl)
if not htmlPage:
return None
return ParseTrackerPage(htmlPage)
def PrepareNewFileName(fileName, fileInfo):
tmp, ext = os.path.splitext(fileName)
toPrepare = fileInfo.name + ' (' + fileInfo.year + ') ' + fileInfo.descr
cleanName = PrepareFileName(toPrepare)
newFileName = cleanName + ext
return newFileName
def MoveFile(src, dst):
shutil.move(src, dst)
def CopyFile(src, dst):
if os.path.isdir(src):
for fileName in os.listdir(src):
if not os.path.exists(dst):
os.mkdir(dst)
subSrc = os.path.join(src, fileName)
subDst = os.path.join(dst, fileName)
CopyFile(src, dst)
else:
if not os.path.exists(dst):
shutil.copy2(src, dst)
def CreateHardLink(src, dst):
CreateHardLinkW = ctypes.windll.kernel32.CreateHardLinkW
CreateHardLinkW.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_void_p)
CreateHardLinkW.restype = ctypes.c_int
if os.path.isdir(src):
for fileName in os.listdir(src):
if not os.path.exists(dst):
os.mkdir(dst)
subSrc = os.path.join(src, fileName)
subDst = os.path.join(dst, fileName)
CreateHardLink(subSrc, subDst)
else:
if not os.path.exists(dst):
if CreateHardLinkW(dst, src, 0) == 0:
raise IOError
def main():
Print('Hello, Find downloads in "%s" :' % INPUT_DIR)
totalCount = 0
processedCount = 0
for fileName in os.listdir(INPUT_DIR):
totalCount = totalCount + 1
Print('Process a file: "%s"' % fileName)
fileInfo = GetDataFromTorrent(fileName)
if fileInfo is None:
continue
sNewFileName = PrepareNewFileName(fileName, fileInfo)
if sNewFileName:
oldFilePath = os.path.join(INPUT_DIR, fileName)
newFilePath = os.path.join(OUTPUT_DIR, sNewFileName)
try:
GetMoveAlgorithms()[MOVE_ALGORITHM](oldFilePath, newFilePath)
processedCount = processedCount + 1
except:
Print("Error, Can't move file from %s to %s" % (oldFilePath, newFilePath))
Print("%d friles were moved from %d total found files" % (processedCount, totalCount))
if __name__ == "__main__":
main()
Работа скрипта проверялась на Windows 7 x86 и Windows 7 x64
В теории скрипт можно портировать и под Linux.
Скрипт заточен под rutracker, но возможно будет работать и с другими сайтами.
По крайней мере после доработки напильником.
Для скачивания html странички я использовал библиотеку urllib2.
А для парсинга .torrent файлов и html я использовал регулярные выражения.
Оказалось, что на Python их использовать весьма удобно.
В принципи для парсинга html лучше было бы использовать css селекторы, но пока и так сойдет.
Так как Python это не мой основной язык, то буду рад советам опытных разработчиков.
Update1:
На случай, если пример с файлом
God.Bless.America.2011.HDTVRiP720.mkv
Вам кажется не убедительным, привожу список топовых файлов с рутрекера.Как по мне, то глаза и голову можно сломать пока поймешь что за фильм скрывается за одним из этих названий.
И естественно программы-каталогизаторы, наподобие AllMyMovies или Movienizer, не смогут в автоматическом режиме найти информацию об этих файлах в базах IMDB и Кинопоиск.
- Na_grani_DVDRp_[rutracker.org]_by_Inсh.avi
- Ohotniki za golovani.chopper887.mkv
- Shvatka.chopper887.mkv
- prizrachnyi.gonschik_2.2012.hdrip.ac3.1450mb.by.riperrr.avi
- Dom_grez_BDRip_dub_[rutracker.org]_by_Scarabey.avi
- Lubov.zhivet.tri.goda.2011.BDRip.avi
- Nepricosaemie.chopper887
- Missiya-Fantom.chopper887.avi
- Njanki.2012.O.DVDRip.IRONCLUB.avi
- samoubyici.2012.dvdrip.ac3.1450mb.by.riperrr.avi
- belyi.tigr.2012.dvdrip.ac3.2050mb.by.riperrr.avi
- Zhila.byla.odna.baba.2011.BDRip.1.46.avi
- svidanie.2012.dvdrip.ac3.1450mb.by.riperrr.avi
- Moy.Paren.Angel.BDRip.avi
- Visotskiy_Spasibo_Chto_Jivoy_2011_DVDRip_1.46_Menen.avi
- Неадекватные люди_1.46.avi
- Den.vyborov.2007.avi
- shapito.shou_1.2010.hdrip.ac3.1450mb.by.riperrr.avi
- belyi.tigr.2012.dvdrip.ac3.1450mb.by.riperrr.avi
- 2 дня_1.46.avi
Update2:
По предложениям в комментариях решил обновить скрипт:
- Перешел на Python 3
- Разделил входной и выходной каталоги
- Добавил поддержку создания HardLink-ов для NTFS
- Добавил поддержку копирования файлов