quinta-feira, 26 de maio de 2016

Como utilizei Python para baixar todos os novos episódios das minhas séries automaticamente


Fala galera, tudo bem? Bom,  semana passada eu fiz um post sobre a versão CLI do Transmission para administrar Downloads de Torrents via Shell porque estava procurando uma maneira de fazer Download de cada novo episódio das minhas séries favoritas, sempre que elas parecerem no RSS de algum blog. Inicialmente eu queria misturar um pouco de Python e como sempre fazer alguma gambiarra com o subprocess pra facilitar a minha como eu sempre faço, mas quando estava quase começando a codar, a luz veio a minha cabeça e eu: "Será que já não existe uma biblioteca para gerenciar torrents para Python? Não cara, com certeza alguém já fez isso..." e lá fui eu buscar uma solução. Para a minha surpresa logo na primeira Googlada eu já encontrei a libtorrent, que pelo que eu li existem mais linguagens que utilizam das adaptações dessa lib. Beleza, mais uma vez que a preguiça ia me fazer trabalhar mais no final, enfim fui salvo...

Site do Python Libtorrent: http://www.libtorrent.org/python_binding.html

Minha ideia era criar um script que funcionaria como um daemon que ficaria rodando em background em um servidor caseiro que eu tenho aqui em casa como Media Server. Eu colocaria ele na inicialização do sistema. ou criaria um Screen e deixaria ele lá, pra sempre, vivendo a vida dele, de horas em horas ele checaria o RSS que eu passaria pra ele, verificaria se novas atualizações e baixaria caso existisse algo diferente lá. Bacana.

Bom, pra fazer isso eu precisaria seguir a seguinte lógica:

1º - Quando rodar o script pela primeira fez, o método de sincronia carregar todas os registros do RSS
2º - Carregar esses registros numa lista, pegar o último registro e salvar numa variável global
3º - Usar um sleep para pegar toda a lista novamente e ver se o ultimo registro é o mesmo da ultima sincronia.
4º - Caso for diferente, ele salva o novo registro na variável de comparação e baixa o torrent do novo episódio.

Bom como qualquer preguiçoso, procurei a maneira mais simples de se fazer, porque afinal, tudo isso nasceu pela pura preguiça de ficar baixando as séries não é mesmo? Seria meio sem sentido fugir do conceito inicial (rs).

Primeiramente criei algumas variáveis que vão ser o 'core' da lógica. Peguei um RSS da série, daquela série lá, que as pessoas seguram a porta, criei uma variável chamada lastHash, que vamos falar dela logo a seguir, uma variável para definir o local onde eu salvaria os arquivos e um tempo que vou usar de sleep para definir os intervalos de cada sync. Criei também uma função que sempre me retorna um json gigantesco com todos os itens do RSS. Para isso, utilizei também uma biblioteca chamada feedparser própria pra esses casos. É só passar o link do feed pra ela, ela faz o request, recebe o response com um JSON que contém os dados e faz o parsing deles par serem tratados de uma forma mais fácil de uma forma parecida com a de um objeto.

 feedRSS = "http://showrss.info/feeds/350.rss"  
 lastHash = None  
 savePath = '/home/matheus/Downloads/Teste'  
 sleeptime = 3600   

Para fazer a comparação da sincronia inicial e do resultado na nova sincronia com o RSS eu decidi gerar uma hash a partir do ultimo item postado no feed e compará-lo com a hash gerada de cada nova sincronia, utilizando o título e o magnetic link que o JSON parseado me retornava. Criei uma função que fazia essa concatenação e me retornava uma hash MD5 com os dados informados. Nada demais também.


Depois criei uma função que tinha a função de teórica de ser um looping infinito que iria fazer a checagem pra sempre dos itens do feed e entrar em sleep após cada tentativa. Novamente iria fazer uma nova sincronia, gerar uma hash com o ultimo resultado e comparar com a anterior. Caso o resultado fosse idêntico, beleza, dorme e tenta de novo daqui há umas horinhas, caso a hash seja diferente, ele chama uma função que seria responsável por baixar o torrent com o magnetic link retornado no ultimo item do JSON.


Aqui vai o pulo do gato. Aqui carreguei uma lista e segui algumas instruções que eu encontrei na documentação do libtorrent depois de ver alguns exemplos. No caso carrego uma lista de parâmetros que levam o path que o arquivo será salvo durante o Download, o tipo do Download, algumas permissões de pause e seed e etc, crio uma nova instância do libtorrent e coloco ele pra ficar de listem nas portas default dos gerenciadores de torrent do sistema, no caso 6881 e 6891.Aqui adicionei também umas variáveis de debug que você pode sempre dar um print caso queira acompanhar a resolução do Download. Como eu fiz o script pra rodar em background, eu não usei. Mas sempre deixo aí pra dar uns prints.


Rodando o projeto pronto

Joguei o código no exemplo no git para tornar a brincadeira mais colaborativa e deixar a criatividade de vocês trabalhar.

Git do projeto: https://github.com/msfidelis/TorrentRSSDownloader

Para baixá-lo basta:
 git clone https://github.com/msfidelis/TorrentRSSDownloader.git  

Caso queira mais opções de séries, eu peguei meus feeds desse link bem bacana que funciona como um indexador dessas paradas.
Mais RSS: https://showrss.info/?cs=feeds

É só alterar lá a variável com o novo link.


Dependências

Python Libtorrent 

Para instalar o Python-Libtorrent é bem simples, caso esteja utilizando algum sistema Debian basta instalar via APT mesmo, caso não esteja, existe uma documentação muito bacana no site do projeto, onde você pode compilar na mão mesmo se for o caso.
 # sudo apt-get build-dep python-libtorrent  
Ou compile a source: https://coderwall.com/p/muvnow/installing-libtorrent-on-linux

Python Feedparser

O feedparser também é tranquilo de instalar. pelo próprio PIP você consegue:
  # sudo pip install feedparser  



Colocando o Script na inicialização do sistema ou em Background

Existem várias formas de se fazer isso, a mais comum é colocar um run do arquivo direto no rc.local do sistema, assim ele vai executar o comando sempre que o sistema subir, mas também você pode criar uma Screen no servidor pra tornar a atividade mais gerenciável

Colocando o script na inicialização dos sistema

Meu servidor caseiro é um Debian 8 Jessie, então é só adicionar a chamada para o script dentro do rc.local do sistema, como:
  # echo 'python /home/matheus/TorrentRSSDownloader/Torrent-Downloader.py & ' >> /etc/rc.local  


Usando uma Screen administrativa no servidor

Há alguns dias antes desse script, postei lá o meu blog um manual de uso do comando Screen do Linux. Fiquem a vontade para ler e entender melhor.

Novamente: Não me responsabilizo pelo mau uso da ferramenta


:)



SOBRE O AUTOR

Matheus Fidelis

http://msfidelis.github.io/

Power Ranger, Piloto de Helicópteros e Astronauta da NASA. Desenvolvedor Web PHP com foco em Backend e POO, Linux SysAdmin DevOps e Entusiasta Python. Criou esse site pra contribuir com a comunidade com coisas que aprende dentro de um setor maluco de TI :)

4 comentários:

  1. Bacana! Eu uso o SickRage para fazer isso: https://sickrage.github.io/

    ResponderExcluir
  2. cara eu to tentando executar porém recebo este erro, será que consegue me ajudar ?
    python Torrent-Downloader.py
    Traceback (most recent call last):
    File "Torrent-Downloader.py", line 4, in
    import libtorrent as lt
    ImportError: dlopen(/usr/local/lib/python2.7/site-packages/libtorrent.so, 2): Symbol not found: __ZN10libtorrent15identify_clientERKNS_10big_numberE
    Referenced from: /usr/local/lib/python2.7/site-packages/libtorrent.so
    Expected in: flat namespace
    in /usr/local/lib/python2.7/site-packages/libtorrent.so

    ResponderExcluir

 
Nanoshots | Open Source Security, Linux e Tutoriais © 2015 - Designed by Templateism.com