parent
19495eeb4a
commit
382d0418ca
|
@ -0,0 +1 @@
|
|||
|
|
@ -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
|
|
@ -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 <start>:<end>")
|
||||
@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()
|
|
@ -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
|
||||
'''
|
||||
)
|
Loading…
Reference in New Issue