Setup logging
parent
dbbe923d5b
commit
2359cf8cac
|
@ -1,36 +1,56 @@
|
|||
import click
|
||||
import subprocess
|
||||
|
||||
import logging
|
||||
|
||||
from anime_downloader.sites.nineanime import NineAnime
|
||||
from anime_downloader.sites.anime import NotFoundError
|
||||
from anime_downloader.sites.exceptions import NotFoundError
|
||||
|
||||
from . import util
|
||||
|
||||
echo = click.echo
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('anime_url')
|
||||
@click.option('--range', 'range_', metavar='<int>:<int>',
|
||||
|
||||
@click.option('--episodes', '-e', 'episode_range', metavar='<int>:<int>',
|
||||
help="Range of anime you want to download in the form <start>:<end>")
|
||||
@click.option('--playlist', default=False, type=bool, is_flag=True,
|
||||
help="If flag is set, saves the stream urls in an m3u file")
|
||||
@click.option('--url', default=False, type=bool, is_flag=True,
|
||||
help="If flag is set, prints the stream url and not download")
|
||||
|
||||
@click.option('--save-playlist', '-p', 'playlist', default=False, type=bool, is_flag=True,
|
||||
help="If flag is set, saves the stream urls in an m3u file instead of downloading")
|
||||
|
||||
@click.option('--url', '-u', default=False, type=bool, is_flag=True,
|
||||
help="If flag is set, prints the stream url instead of downloading")
|
||||
|
||||
@click.option('--play', 'player', metavar='PLAYER',
|
||||
help="Streams in the specified player")
|
||||
|
||||
@click.option('--no-download', default=False, is_flag=True,
|
||||
help="Retrieve without downloading")
|
||||
@click.option('--quality', type=click.Choice(['360p', '480p', '720p']),
|
||||
|
||||
@click.option('--quality', '-q', type=click.Choice(['360p', '480p', '720p']),
|
||||
default='720p',
|
||||
help='Specify the quality of episode. Default-720p')
|
||||
@click.option('--force', is_flag=True, default=False,
|
||||
|
||||
@click.option('--force', '-f', is_flag=True, default=False,
|
||||
help='Force downloads even if file exists')
|
||||
def cli(anime_url, range_, playlist, url, player, no_download, quality, force):
|
||||
|
||||
@click.option('--log-level', '-ll', 'log_level',
|
||||
type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR']),
|
||||
default='INFO',
|
||||
help='Sets the level of logger')
|
||||
|
||||
def cli(anime_url, episode_range, playlist, url, player, no_download, quality,
|
||||
force, log_level):
|
||||
""" Anime Downloader
|
||||
|
||||
Download your favourite anime.
|
||||
"""
|
||||
util.setup_logger(log_level)
|
||||
|
||||
try:
|
||||
anime = NineAnime(anime_url, quality=quality,
|
||||
callback=lambda message: print('[INFO] '+message))
|
||||
anime = NineAnime(anime_url, quality=quality)
|
||||
except NotFoundError as e:
|
||||
echo(e.args[0])
|
||||
return
|
||||
|
@ -38,15 +58,15 @@ def cli(anime_url, range_, playlist, url, player, no_download, quality, force):
|
|||
if url or player:
|
||||
no_download = True
|
||||
|
||||
if range is None:
|
||||
range_ = '1:'+str(len(anime)+1)
|
||||
if episode_range is None:
|
||||
episode_range = '1:'+str(len(anime)+1)
|
||||
|
||||
try:
|
||||
start, end = [int(x) for x in range_.split(':')]
|
||||
start, end = [int(x) for x in episode_range.split(':')]
|
||||
anime._episodeIds = anime._episodeIds[start-1:end-1]
|
||||
except ValueError:
|
||||
# Only one episode specified
|
||||
anime = [anime[int(range_)-1]]
|
||||
anime = [anime[int(episode_range)-1]]
|
||||
|
||||
for episode in anime:
|
||||
if url:
|
||||
|
|
|
@ -2,26 +2,21 @@ import requests
|
|||
from bs4 import BeautifulSoup
|
||||
import json
|
||||
import re
|
||||
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import click
|
||||
import logging
|
||||
|
||||
|
||||
class AnimeDLError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class URLError(AnimeDLError):
|
||||
pass
|
||||
|
||||
|
||||
class NotFoundError(AnimeDLError):
|
||||
pass
|
||||
from .exceptions import AnimeDLError
|
||||
|
||||
|
||||
class BaseAnime():
|
||||
def __init__(self, url, quality='720p', callback=None):
|
||||
QUALITIES = None
|
||||
_episodeClass = None
|
||||
|
||||
def __init__(self, url, quality='720p'):
|
||||
|
||||
if quality not in self.QUALITIES:
|
||||
raise AnimeDLError('Incorrect quality: "{}"'.format(quality))
|
||||
|
@ -33,9 +28,7 @@ class BaseAnime():
|
|||
else:
|
||||
raise AnimeDLError(f'Quality {quality} not found in {self.QUALITIES}')
|
||||
|
||||
self._callback = callback
|
||||
if self._callback:
|
||||
self._callback('Extracting episode info from page')
|
||||
logging.info('Extracting episode info from page')
|
||||
self.getEpisodes()
|
||||
|
||||
def verify_url(self, url):
|
||||
|
@ -52,7 +45,7 @@ class BaseAnime():
|
|||
|
||||
def __getitem__(self, index):
|
||||
ep_id = self._episodeIds[index]
|
||||
return self._episodeClass(ep_id, self.quality, callback=self._callback)
|
||||
return self._episodeClass(ep_id, self.quality)
|
||||
|
||||
def _getEpisodeUrls(self, soup):
|
||||
return
|
||||
|
@ -63,23 +56,21 @@ class BaseEpisode:
|
|||
title = ''
|
||||
stream_url = ''
|
||||
|
||||
def __init__(self, episode_id, quality='720p', callback=None):
|
||||
def __init__(self, episode_id, quality='720p'):
|
||||
|
||||
if quality not in self.QUALITIES:
|
||||
raise AnimeDLError('Incorrect quality: "{}"'.format(quality))
|
||||
|
||||
self.episode_id = episode_id
|
||||
self.quality = quality
|
||||
self._callback = callback
|
||||
if self._callback:
|
||||
self._callback("Extracting stream info of id: {}".format(self.episode_id))
|
||||
logging.info("Extracting stream info of id: {}".format(self.episode_id))
|
||||
self.getData()
|
||||
|
||||
def getData(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def download(self, force=False):
|
||||
print('[INFO] Downloading {}'.format(self.title))
|
||||
logging.info('Downloading {}'.format(self.title))
|
||||
path = './' + self.title
|
||||
r = requests.get(self.stream_url, stream=True)
|
||||
|
||||
|
@ -89,19 +80,17 @@ class BaseEpisode:
|
|||
|
||||
if os.path.exists(path) and not force:
|
||||
if os.stat(path).st_size == total_size:
|
||||
print('[INFO] File already downloaded. Skipping download.')
|
||||
logging.warning('File already downloaded. Skipping download.')
|
||||
return
|
||||
|
||||
if r.status_code == 200:
|
||||
with click.progressbar(length=int(total_size)) as bar:
|
||||
with open(path, 'wb') as f:
|
||||
for chunk in r.iter_content(chunk_size=chunksize):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
downloaded += chunksize
|
||||
# write_status((downloaded), (total_size),
|
||||
# start_time)
|
||||
bar.update(chunksize)
|
||||
with open(path, 'wb') as f:
|
||||
for chunk in r.iter_content(chunk_size=chunksize):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
downloaded += chunksize
|
||||
write_status((downloaded), (total_size),
|
||||
start_time)
|
||||
|
||||
|
||||
def write_status(downloaded, total_size, start_time):
|
||||
|
@ -113,5 +102,5 @@ def write_status(downloaded, total_size, start_time):
|
|||
status = 'Downloaded: {0:.2f}MB/{1:.2f}MB, Rate: {2:.2f}KB/s'.format(
|
||||
downloaded, total_size, rate)
|
||||
|
||||
sys.stdout.write("\r\n" + status + " "*5 + "\r")
|
||||
sys.stdout.write("\r" + status + " "*5 + "\r")
|
||||
sys.stdout.flush()
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
class AnimeDLError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class URLError(AnimeDLError):
|
||||
pass
|
||||
|
||||
|
||||
class NotFoundError(AnimeDLError):
|
||||
pass
|
|
@ -1,4 +1,5 @@
|
|||
from .anime import BaseAnime, BaseEpisode, AnimeDLError, URLError, NotFoundError
|
||||
from .anime import BaseAnime, BaseEpisode
|
||||
from .exceptions import AnimeDLError, URLError, NotFoundError
|
||||
import json
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
@ -7,6 +8,8 @@ import re
|
|||
import time
|
||||
|
||||
|
||||
__all__ = ['NineAnimeEpisode', 'NineAnime']
|
||||
|
||||
class NineAnimeEpisode(BaseEpisode):
|
||||
QUALITIES = ['360p', '480p', '720p']
|
||||
_base_url = r'https://9anime.is/ajax/episode/info?id={id}&server={server}&_={param_}&ts={ts}'
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import logging
|
||||
|
||||
def setup_logger(log_level):
|
||||
if log_level == 'DEBUG':
|
||||
format = '%(levelname)s %(name)s: %(message)s'
|
||||
else:
|
||||
format = '%(levelname)s:%(message)s'
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.getLevelName(log_level),
|
||||
format=format
|
||||
)
|
Loading…
Reference in New Issue