Cериалокачалка на python3 с поддержкой расширений

    В качестве вступления стоит сказать что я пользуюсь macOS и потому некоторые части:


    • Автозапуск (launchd)
    • Формат конфигурационных файлов (plist)
    • Программа, используемая для уведомлений (terminal-notifier)

    будут специфичны для этой ОС. Однако, если Вас заинтересует проект, думаю, поменять пару путей и слегка поправить несколько функций, чтобы заставить этот код работать с Вашей системой уведомлений, yaml'ом и, допустим, кроном, не составит труда.


    Итак, к делу.


    Проверять трекеры на обновления любимых телевизионных шоу, вспоминать в момент когда вышел новый эпизод, смотрел ли ты предыдущий, — надоедает. К тому же, как известно, все что нужно делать больше двух раз, стоит автоматизировать. Проект был начат на скорую руку и, вероятно, будет совершенствоваться.


    Что же он содержит?


    1. Класс парсера в parser.py
    2. Класс загрузчика в core.py
    3. Плагины, наследующие класс загрузчика в директории plugins
    4. Файлы конфигурации плагинов в директории configs
    5. Директорию icons для иконок уведомлений
    6. Файл main.py, дергающий плагины
    7. Файл install.py

    Класс парсинга


    Так как почти на всех сайтах сериалов есть свои RSS-ленты, было решено для упрощения процесса написания плагинов слепить функцию парсинга, позволяющую автоматически распарсить rss по ссылке и выдать список пар (заголовок, ссылка) с возможностью указания кодировки.


    Чуть позже пришла необходимость простого парсинга html, а потом подумалось что некоторые сайты могут отдавать ссылки и через api в формате json.


    Так функция превратилась в класс, хранящий сессию (requests Session) для сайтов, требующих авторизации и возвращающий response-объект с методами html(), rss(), json() и auto(). Последний пытается угадать содержимое (xml, html или json) и кодировку по заголовку 'Content-Type'. По умолчанию — 'utf-8' и html.


    • Метод html() возвращает объект beautifulsoup всей страницы
    • Метод rss() вызвращает массив кортежей (заголовок, ссылка)
    • Метод json() возвращает объект, полученный методом json.loads текста страницы

    Класс загрузчика


    Предоставляет плагинам методы parse() и download().


    • Метод parse() предоставляет возможность передать ссылку и параметры url. Он же проверяет 'If-Modified-Since' если сайт предоставляет данные о последнем изменении. Возвращает response-объект из файла parse.py.
    • Метод download() принимает словарь с данными о названии сериала, эпизода, ссылкой и прочими мелочами, а так же http-заголовки и куки. А далее самостоятельно производит всю магию. Загружает файл в предварительно созданную им папку "Название_сериала[имя_класса_плагина]", где предполагается что имя класса плагина — название студии озвучания/сайта с которого происходит загрузка. Если файл — торрент, загружает эпизод с торрента и удаляет файл торрента. Загрузка производится с помощью aria2c, который должен быть установлен в системе и находиться в одной из директорий, прописанных в $PATH. После чего вызывается метод save(), который сохраняет ссылки в файл конфигурации для предотвращения повторной загрузки.
    • Метод __notify(), который вызывается при начале и окончании загрузки, если по пути /usr/local/bin/terminal-notifier обнаружено соответствующее приложение. Посмотреть как это выглядит можно чуть ниже.

    Плагины


    Классы, наследующие класс загрузчика, реализующие метод start() в котором надо произвести парсинг и вызвать метод download() с ожидаемыми параметрами.


    Файлы конфигурации плагинов


    *.plist


    Содержат:


    • Интересующее качество
    • Список подписок
    • Список исключений ("полный сезон", например)
    • last_modified для сайтов, дающих информацию о последнем изменении
    • Сюда же будет записан список ссылок для предотвращения повторной загрузки

    Директория icons


    Папка в которую можно положить файлы иконок, которые будут использованы при уведомлении о загрузке/окончании загрузки эпизодов из соответствующих источников. Названия иконок должны соответствовать названиям плагинов, но с расширением jpg/ico/png.


    main.py


    Дергает поочередно метод start() всех плагинов в директории plugins.


    install.py


    • Установит зависимости
    • Переместит файлы проекта в ~/.NB-series-downloader
    • Создаст файл автозапуска
    • Удалит директорию склонированного репозитория

    Автозагрузка


    Файл install.py сделает это за Вас, но если Вы решили сделать все вручную, то...


    Инструкция

    Мне не удалось рассказать launchd о $HOME, посему Вам придется самостоятельно заменить в тексте ниже $HOME на путь до домашнего каталога вашего пользователя /Users/Username и, возможно, изменить путь до директории со скриптами, если вы положили их в другое место.


    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Disabled</key>
        <false/>
        <key>EnvironmentVariables</key>
        <dict>
            <key>PATH</key>
            <string>/usr/local/bin</string>
        </dict>
        <key>KeepAlive</key>
        <dict>
            <key>SuccessfulExit</key>
            <false/>
        </dict>
        <key>Label</key>
        <string>series_downloader</string>
        <key>ProgramArguments</key>
        <array>
            <string>python3</string>
            <string>$HOME/.NB-series-downloader/main.py</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>900</integer>
        <key>WorkingDirectory</key>
        <string>$HOME/.NB-series-downloader</string>
    </dict>
    </plist>

    Сам файл с этим содержимым стоит назвать series_downloader.plist и положить в ~/Library/LaunchAgents/.
    Загрузить описанные в этом файле задания сразу можно командой


    launchctl load ~/Library/LaunchAgents/series_downloader.plist

    Иначе задания активируются при следующей загрузке компьютера.
    Эти действия заставят main.py, лежащий в директории $HOME/.NB-series-downloader/, запускаться каждые 900 секунд (15 минут).


    Итого


    Ссылка на Github.


    Честно говоря, первое что я туда выкладываю, так что мог напортачить. Подскажите, если что не так.


    Уведомление о начале загрузки:


    Уведомление о начале загрузки
    После загрузки надпись "Загрузка начата" сменится на "Загрузка закончена".
    Вот и все что мы увидим в результате работы плагина, а эпизоды будут аккуратненько сложены в папочку и ждать своего часа.


    Сериалы в моем случае складываются в Series в том же каталоге (можно указать иное место в self.series_dir класса downloader в core.py).


    А для просмотра загруженных серий мною написан workflow для Alfred 3:
    Список сериалов
    После просмотра каждой серии он предлагает:


    • Удалить оную (я не храню архив, всё просмотренное отправляется в корзину)
    • Запрашивает оценку эпизода от 1 до 5, а так же отмечает только что просмотренную таковой в моем аккаунте на myshows.me и выставляет рейтинг эпизода используя их api
    • Выводит уведомление о том удачно ли все прошло
    • По клику на уведомление можно открыть страницу только что просмотренного эпизода на myshows

    Но это всё — уже совсем другая история...

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 44

      0
      Спасибо за статью, попробую перепилить это на малину! Пока что пользуюсь Torrent Monitor от вашего однофамильца :), но оно на php + сама выкачка торрентов отдельной программой.
        0
        Удачи :)
        Дайте знать что получится.
        И, если возможно, выложите куда-нибудь… на тот же github.
        Подумываю о покупке малинки давно, может, воспользуюсь, если самому переписывать лень будет.
        Да и еще кому-нибудь явно полезно будет.
          0
          Давно была статься на хабре про парсинг rss и написание не большого скрипта у меня вот такой вышел, можно даже с сайтов где требуется авторизация wget поддерживает это.

          habrahabr.ru/post/87042

          wget -qO — coldfilm.ru/news/rss | grep -oe 'http.*.torrent' | grep -ie '\(Matter\|Killjoys\|Robot\|Orange\|Wayward\|Preacher\|100\|Legends\|Dreadful\|Supernatural\|Shannara\|Limitless\|Carter\|Lucifer\|11.22.63\|Walking\|Shameless\|Grimm\|Second\|Tomorrow\|Elementary\|Colony\|Marvels\|gotehm\|Quantico\|Thrones\|Gotham\|Americans\|Heartbeat\|Quantico\|Upon\|Musketeers\|houdini\|Containment\)' | grep -ie 720p | wget -nc -qi — -P /var/lib/transmission-daemon/downloads > /dev/null 2>&1
            0

            Имеет право на жизнь, когда-то пользовался подобным скриптом.
            Только вот он, как минимум, не предотвращает повторную загрузку того же эпизода и не обращает внимание на 'last_modified'.

              0

              На лостфильм last_modified был сломан, не знаю как сейчас… Пока я это выяснил, упустил несколько эпизодов! Пришлось отключить...

                0

                Работает как часы.

                  +1

                  Нет им больше доверия! :)

            0
            Добрался позавчера таки взять себе последнюю малинку и сегодня адаптировал сие свое творение для нее.
            Та же aria2c для загрузки, а вот функция уведомления пока pass.
            Может, допишу в ней чтоб уведомления об окончании загрузки… не знаю… в телеграм, что ли, присылало. Или vk.
            Но основная функциональность уже работает. В cron только задачу создать осталось.
            Если Вам или кому-то еще нужно — обращайтесь в личные сообщения, поделюсь.
              0
              Для уведомлений можно использовать pushbullet. Довольно удобно.
                0
                Кстати, имел дело с этим сервисом. Приятный. Но не вижу резона плодить сущности без необходимости.
                  –1
                  Использую его для уведомлений. Удобно получать их на любом устройстве. Всё же лучше чем ВК.
                  0

                  О! Спасибо, удобная штука!

                    0
                    Столкнулся с их ограничениями, теперь часть уведомлений перевёл на pushover. Там свои приятные фишки.
                      0

                      Только у них это платно: After a 7-day free trial, it costs $4.99 USD once, per-platform (iOS, Android, Desktop)

                        0
                        Да.
                          0
                          Есть ещё такой, совсем бесплатный https://simplepush.io
                            0
                            Только для андроидов?
                +1
                Интересно когда производители видео проигрывателей смогут это сделать в своих устройствах и не нужно будет колхозить свои решения. Кто владелец Apple TV 4 расскажите там уже появилась такая функция.
                  +3
                  Скачивание сериалов с торрентов не совсем легально с точки зрения авторского права.

                    +1
                    Соглашусь, что размещение на торрентах сериалов не совсем легально. Я так предполагаю, что это единственный доступный канал поставки зарубежных сериалов с русской озвучкой в очень сжатые сроки. Я ранее смотрел обзоры и компании «поставщиков медиаконтента» и не смог найти достаточно быстро поставляющих качественный контент с хорошей скоростью. Смотрел правда только наиболее популярные вроде (NetFlix, IVI и т.д.) Возможно сегодня ситуация поменялась в лучшую сторону?
                  +1

                  flexget пробовали?

                    0
                    Что-то не въехал как пользовать
                      0

                      ставите flexget, пишете конфиг «откуда брать, чем качать, что со скачанным делать потом» (плагины для чуть менее, чем всего вообще, присутствуют в коробке) втыкаете в автозапуск и забываете навсегда.

                        0
                        то есть, развесистая штука, которой я никогда пользоваться в полной мере не буду, так?
                          0

                          Да. И которая легко переживёт смену хостинга сериалов, источника новых эпизодов/фильмов, скачивалки этого всего добра и места его хранения

                            0

                            Наверное, удобно, но не так часто сайты по хостингам ездят и адреса меняют. А менять aria2 на что-либо еще мне лично ни к чему. В любом случае, я пока могу найти 5-7 минут раз в 3 года чтобы переписать метод скачки торрента под новую торрентокачалку, исправить адрес сайта в плагине и поправить парсинг страницы, если изменится ее формат.
                            И при этом не тащить за собой лишний проект с тучей плагинов.
                            А вообще, вечерком погляжу на это дело. Может, и правда годно стало.

                              0
                              Наверное, удобно, но не так часто сайты по хостингам ездят и адреса меняют.

                              гораздо чаще оказывается, что один сериал удобнее брать у LostFilm, другой у NovaFilm, а третий вообще из файлообменников/usenet

                                0

                                Оттого для себя и начинал писать этот проект. Потому как, допустим, Wayward Pines от LostFilm, Королевство от NewStudio, Кремниевая Долина от ColdFilm. Вот и решил написать основу, которая будет наследоваться, а разбор сайтов на заголовки/ссылки добавить поверх унаследованного — 3, ну 5 минут времени на каждый. Максимум. А в случае с RSS и того меньше.
                                P.S. Нисколько не умаляю заслуг ребят, делающих FlexGet, но мне он как когда-то по душе не пришелся, так и никак. Как было так и осталось ощущение что слишком много всего накручено.
                                P.P.S. Возможно, мне просто хотелось свой велосипед изобрести. Он ездит. И это хорошо :)

                          0
                          Выглядит оно громоздко, еще и руби надо ставить :) А памяти сколько кушает? Умеет оно логиниться на сайт?
                            0
                              +1
                              Эм, извините, под вечер глаза замылены, показалось, что там rake tasks описаны :)
                      +1
                      Давно есть http://litr.cc/, а вообще проще подписку оформить, легальных сервисов много.
                        0

                        Видел их поделие. Пользовался как-то. Отказался. Не помню почему. В целом неплохо, но...


                        • еще один сервис, на котором надо иметь аккаунт
                        • единая точка отказа для всех трекеров
                        • можно удалить оба плагина в моем проекте и написать один, который будет парсить RSS litr.cc
                          качать с него, ведь, тоже как-то надо
                        0
                        Привет однофамильцам и единомышленникам :))))
                        Мне только кажется что не хватает гуя для настройки, на том же PyObjC… ну и расширять список трекеров, понятное дело :)
                          0
                          Не очень хочется заморачиваться с гуём. Если кто-то напишет, добавлю в проект.
                          Плагины для baibako и coldfilm написал сегодня. С утра, думаю, соберусь добавить.
                            0
                            А какие вообще планируется трекеры добавлять? kinozal, rutracker?
                          0
                          Как говорится у дураков мысли сходятся. Я начал писать аналог для своего медиа сервера. Только я это решил делать на java. Надеюсь черпать вдохновение из вашего проекта ;)
                            0
                            Надеюсь, удастся.
                            Удачи)
                              0
                              Похожую проблему решаю генерацией календарей в формате iCal (импорт этого формата поддерживает iCloud Calendar и Google Calendar). Даты выхода эпизодов забираю из www.themoviedb.org/documentation/api
                              0
                              У меня тоже есть аналог на python2, с красивой веб мордой на ангуляр материал:
                              github.com/werwolfby/monitorrent
                              Пользуюсь на cubietruck через docker (есть образ на докер хабе).

                              Писал на питоне 2, чтобы без проблем запускать на роутерах.

                              До этого пользовался torrent monitor, но было пару проблем, и автор удалил сырцы с гитхаба.

                              Может объеденим усилия?
                              0
                              Flexget имеет очень много, но его настройка с первого захода получится мало у кого. хочется простую стабильную гуевую тулзу, чтобы указал ей что и в каком качестве качать. Так что господа, вы делаете хорошее дело, только каждый свое и будет очень здорово, если вы, объединив усилия, дадите нам это.
                                0
                                Тоже намучался с флексгетом, хотя стоит отдать ему должное, много чего можно.
                                Но например тот же лосфильм там подключается с танцами с бубном. Гуи все ещё ужасен и коцает настроенные ямлы.

                                Но зато можно действительно гибкие правила настраивать.

                                У меня была настроена скачка всех фильмов этого и предыдущего года с качеством 720p (больше инет не позволял) и рейтингом на imdb >= 6.
                                И это было круто, кто-то рассказал про хороший фильм, а он у тебя уже скачан )

                                Предлагаю посмотреть на наш Monitorrent
                                Это не флексгет, но у меня есть дикое желание подключить к нам плагины флексгета.

                                Вообще планов по развитию очень много
                                0
                                Хорошо бы внедрить поддержку русских источников в sickbeard. Сильно не хватает.

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое