Хочу поделиться небольшим скриптом, который делает для меня простую, но весьма полезную вещь — производит групповое переименование скачанных файлов так, что файлы получают удобно читаемое имя со страницы на сайте торрент трекера.
В итоге вместо
В продолжение к теме Можно ли прибраться на компе раз и навсегда?
В общем вот что делает скрипт: производит поиск по каталогу 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
- Добавил поддержку копирования файлов
