Simple and flexible API for jut.su.
As a weeb, I have my own favourite site for watching anime. Now that I am also a super h4ck3r, I created an API for accessing this site and it turned out pretty well.
Install the module from PyPi:
pip install jutsu-api
Then import it just like that:
from jutsu_api import API
API(verbosity:int = 0)
Class API
is a singleton and can be initialized with
one parameter verbosity
, which is responsible on how
much feedback the API sends. The feedback is being printed to stderr,
the default verbosity level is 0
.
.verbosity(v:int)
Set vebosity level explicitly.
.search(keyword:str = "", filter:Filter = Filter(), maxpage:int = -1) -> list[Anime]
Searches the site for anime with given keyword and filter.
The Filter
object is explained later.
maxpage
parameter is used to limit the output by stopping
parsing after an amount of pages. -1
is the default value,
and means that there should be no limitation. A list of Anime
objects is returned. If there are no results, the list will be empty.
.anime(id:str) -> Anime
Returns Anime
object generated by parsing the id
of that anime.
Anime's id is used and can be found in the link to the anime.
Example id
: stein-gate
.episode(id:str) -> Episode
Returns a single Episode
object generated by parsing the id
of that episode.
Episode's id is the path link to the episode.
Example id
: stein-gate/season-1/episode-1.html
Anime(
name:Name|None = None,
thumbnail:str|None = None,
info:Filter|None = None,
years:list[int]|None = None,
age:int|None = None,
description:str|None = None,
content:Content|None = None,
ongoing:bool|None = None,
id:str|None = None
)
Class Anime
provides a full information about the selected anime.
Parsing anime from API.search()
does not give full information,
therefore some parameters have a getter, and if the corresponding parameter is None
,
additional information is being fetched from anime's main page.
All parameters are optional, but at least one of name:Name, id:str
must be specified.
.download(quality:int|None = None, path:str = "", threads:int = 1)
Downloads the whole anime, walking over seasons and episodes
iteratively and downloading each. quality
parameter specifies
the quality of the videos to be downloaded.
If quality
is None
, highest quality will be used.
threads
parameter with default value 1
, if it is specified to be not equal 1
,
will create a ThreadPool and download simultaneously.
Downloading whole anime will create a folder with it's name and subfolders for seasons.
Parameter path
will add a path in front of the output file and save the file
where specified.
Example quality
: 720
.selector:Selector
Property of an Anime
object, helps with selecting specific episodes for download.
See more in Selector
Content(seasons:list[Season], films:Season|None = None)
Content
object provides an accessor for the Season
s and films of an anime.
Some animes have no films, therefore sometimes the parameter films
is None
.count:int
The count property gives the total count of episodes in seasons.
Season(title:str|None, episodes:list[Episode], name:Name|None = None)
A Season
may be a normal season or the container for anime's films.
Seasons' title
is the general name of the season, which is moslty Season <number>
or Full-length Films
for films container.
State of name
can be different in following situations:
- Anime has only one season: name is
None
- Anime has multiple unnamed seasons: name's
id
is present - Anime has mutliple named seasons: name is fully present
More about Name
object is written further down.
.download(quality:int|None = None, path:str = "", threads:int = 1)
Pretty much the same as Anime.download()
.
path
is added in front of all locations, so that
the actual downloading happens at that location.
Creates folders if the anime has multiple seasons,
downloads in the final folder directly, if the season is only one.
Episode(
title:str|None = None,
name:Name|None = None,
duration:int|None = None,
opening:Opening|None = None,
ending:Ending|None = None,
players:list[Player]|None = None,
thumbnail:str|None = None,
preview:str|None = None,
id:str|None = None
)
Pretty much the same as Anime
class.
title
is the general name of the episode.
Fetching episode from Anime
and getting it with
an id from API.anime()
will produce different titles.
duration
is the length of the episode in seconds.
preview
and thumbnail
are links to pictures of
the preview and thumbnail respectively.
Opening
and Ending
objects will be explained later.
players
property is a list of Player
objects,
which also will be explained later.
.download(quality:int|None = None, path:str = "")
Downloads an episode with given quality
.
If quality
is None
, highest quality will be used.
path
will be added to the title and the episode
will be downloaded into the resulting file.
.player(quality:int|None = None) -> Player|None
Gets a player with the given quality
or
returns None
if the player is not found.
If quality
is None
, returns highest quality player.
Opening(begin:int, end:int, link:str)
begin
and end
are timestamps of the opening.
link
is the link to the music provided by the site.
Ending(begin:int, link:str)
Pretty much the same as the Opening
class.
Player(quality:int|None = None, link:str)
Internal object to manage the video of an episode.
.download(local:str|None = None)
Downloads the video to a local file with the name
of parameter local
. If it is None
then the
file name used on the server will be chosen.
Filter(
genres:list[Name] = [],
types:list[Name] = [],
years:list[Name] = [],
sorting:list[Name] = [],
link:str|None = None
)
The Filter
object is used to filter out
results in searching the API, or to describe
an already found anime with it's genres, types,
publishing years etc. In addition to those
lists, a link can be given, which describes the filter.
Example link
: adventure-comedy-game/2000-2007-and-2008-2014/
Filter.available:Filter
Static property of the object Filter
, gives
back another Filter
object, which has all
the genres, types etc. available on the site.
Name(name:str|None, id:str, orig:str|None = None)
The Name
object is used in various places to name things.
Since the jut.su site is in russian language, the name
is the visible name, orig
is the english or japanese name
and id
is the id used on the site for navigation, fetching etc.
Selector(parent:Anime)
A helper object for specific selections of episodes for download.
.select_episodes(quality:int|None = None, items:Iterable[int]|None = None) -> Downloader
Selects episodes with specific indexes. This ignores seasons and
counts each next episode as index + 1
. Be careful: Index of episodes starts with a 0
.
If items
is None
, everything will be selected.
The selection quality is the parameter quality
. If it is None
, highest
quality will be selected.
.select_seasons(quality:int|None = None, items:Iterable[int]|None = None) -> Downloader
Selects seasons with specific indexes. Those selected seasons are selected
completely including all their episodes. Indexing begins with a 0
.
If items
is None
, everything will be selected.
The selection quality is the parameter quality
. If it is None
, highest
quality will be selected.
.select_in_seasons(quality:int|None = None, items:dict[int, Iterable[int]|None]) -> Downloader
Selects specific episodes in specific seasons. Seasons index goes into
the key of dictionary, the value is an iterator of indexes inside this episode.
The selection quality is the parameter quality
. If it is None
, highest
quality will be selected.
Downloader(items:list[list[Player, str]])
The object being returned from Selector
.
.add(downloader:Downloader)
Adds items of another downloader to itself. Created for merging queues.
.download(path:str = "", threads:int = 1)
Downloads the queue of the object using threads and a path
, which is being added
in front of the location.
The following example will download the anime "One Punch Man" into weeb's secret anime folder in full quality and will use 3 threads to download simultaneously.
from jutsu_api import API
api = API(verbosity = 1)
search = api.search(keyword = "punch")
onepunch = search[0]
onepunch.download(
path = "/home/weeb/homework/",
threads = 3
)
This example uses Selector
to download everything after episode 5:
from jutsu_api import API
api = API(verbosity = 1)
search = api.search(keyword = "punch")
onepunch = search[0]
episodes = onepunch.selector.select_episodes(
range(5, onepunch.content.count)
)
episodes.download(
path = "/home/weeb/homework/",
threads = 3
)