diff --git a/anime_downloader/__init__.py b/anime_downloader/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/anime_downloader/__init__.py @@ -0,0 +1 @@ + diff --git a/anime_downloader/anime.py b/anime_downloader/anime.py new file mode 100644 index 0000000..b3c936b --- /dev/null +++ b/anime_downloader/anime.py @@ -0,0 +1,75 @@ +import requests +from bs4 import BeautifulSoup +import json + + +QUALITIES = ['360p', '480p', '720p'] + + +class AnimeDLError(Exception): + pass + + +class URLError(AnimeDLError): + pass + + +class NotFoundError(AnimeDLError): + pass + + +class Anime: + def __init__(self, url, quality='720p'): + + if quality not in QUALITIES: + raise AnimeDLError('Incorrect quality: "{}"'.format(quality)) + + self.url = url + self.quality = quality + self.getEpisodes() + + def getEpisodes(self): + self._episodeIds = [] + r = requests.get(self.url) + soup = BeautifulSoup(r.text, 'html.parser') + episodes = soup.find_all('ul', ['episodes']) + episodes = episodes[:int(len(episodes)/3)] + + for x in episodes: + for a in x.find_all('a'): + ep_id = a.get('data-id') + self._episodeIds.append(ep_id) + + def __len__(self): + return len(self._episodeIds) + + def __getitem__(self, index): + ep_id = self._episodeIds[index] + return Episode(ep_id, self.quality) + + +class Episode: + _base_url = r'https://9anime.is/ajax/episode/info?id={0}&server=33' + + def __init__(self, episode_id, quality='720p'): + + if quality not in QUALITIES: + raise AnimeDLError('Incorrect quality: "{}"'.format(quality)) + + self.episode_id = episode_id + self.quality = quality + self.getData() + + def getData(self): + url = self._base_url.format(self.episode_id) + data = json.loads(requests.get(url).text) + url = data.get('target') + r = requests.get(url+'&q='+self.quality) + soup = BeautifulSoup(r.text, 'html.parser') + try: + self.stream_url = soup.find_all('source')[0].get('src') + except IndexError: + raise NotFoundError("Episode not found") + + def download(): + pass diff --git a/anime_downloader/cli.py b/anime_downloader/cli.py new file mode 100644 index 0000000..158f28f --- /dev/null +++ b/anime_downloader/cli.py @@ -0,0 +1,37 @@ +import click +from .anime import Anime + +echo = click.echo + + +@click.command() +@click.argument('anime_url') +@click.option('--range', help="Range of anime you want to" + " download in the form :") +@click.option('--playlist', default=False, help="If falaf is set, saves the" + " stream urls in an m3u file", type=bool, is_flag=True) +@click.option('--url', default=False, help="If flag is set, prints the" + " stream url and not download", type=bool, is_flag=True) +def cli(anime_url, range, playlist, url): + """ Anime Downloader + + Download your favourite anime. + """ + anime = Anime(anime_url) + + if range is None: + range = '1:'+str(len(anime)+1) + + try: + start, end = [int(x) for x in range.split(':')] + anime._episodeIds = anime._episodeIds[start-1:end-1] + except ValueError: + # Only one episode specified + anime = [anime[int(range)-1]] + + for episode in anime: + if url: + print(episode.stream_url) + continue + + episode.download() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..54e3698 --- /dev/null +++ b/setup.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +from setuptools import setup, find_packages + +setup( + name='anime-downloader', + version='1.0', + packages=find_packages(), + # py_modules=['anime_downloader'], + install_requires=[ + 'bs4', + 'requests', + 'Click', + ], + entry_points=''' + [console_scripts] + anime-dl=anime_downloader.cli:cli + ''' +)