Metadata-Version: 2.4
Name: anime_parsers_ru
Version: 1.17.0
Summary: Python package for parsing russian anime players
Author-email: YaNesyTortiK <ya.nesy.tortik.email@gmail.com>
Maintainer-email: YaNesyTortiK <ya.nesy.tortik.email@gmail.com>
Project-URL: Homepage, https://github.com/YaNesyTortiK/AnimeParsers
Project-URL: Issues, https://github.com/YaNesyTortiK/AnimeParsers/issues
Keywords: anime,parser,kodik,parsing,aniboom,animego,cvh,jutsu,shikimori,kodikapi,kodik api,аниме,парсинг,кодик,парсер,анибум,анимего,джутсу,шикимори,кодик апи
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: beautifulsoup4>=4.14.0
Requires-Dist: requests[socks]>=2.32.0
Provides-Extra: async
Requires-Dist: aiohttp>=3.10.0; extra == "async"
Requires-Dist: aiohttp-socks>=0.11.0; extra == "async"
Provides-Extra: lxml
Requires-Dist: lxml>=6.0.0; extra == "lxml"
Dynamic: license-file

# AnimeParsers
[![PyPI - Downloads](https://img.shields.io/pypi/dm/anime-parsers-ru?label=PyPI%20downloads)
]() [![PyPI - Version](https://img.shields.io/pypi/v/anime-parsers-ru)
]()
## Описание
Данный проект нацелен на создание наиболее широкого спектра парсеров на python для различных аниме-плееров в русскоязычном/снг сегменте

Актуальная стабильная версия доступна на [pypi](https://pypi.org/project/anime-parsers-ru/) или в [релизах](https://github.com/YaNesyTortiK/AnimeParsers/releases) на гитхабе 

## Что есть на данный момент
- [x] Парсер Kodik (__требуется api ключ__) (+ асинхронный)
- [x] Парсер Animego (api ключ не требуется)(+ асинхронный)
    - [x] Парсер плеера Aniboom
    - [x] Парсер плеера CVH
- [x] Парсер JutSu (без функции поиска, не требует api ключей) (доступно через прокси)
- [x] Парсер Shikimori (с возможностью использовать псевдо-api, не требует api ключей) (+ асинхронный)

## Установка
- Стандартная установка:
    ```commandline
    pip install anime-parsers-ru
    ```
- Установка с lxml:
    ```commandline
    pip install anime-parsers-ru[lxml]
    ```
    Для использования lxml при инициализации парсера установите параметр `use_lxml = True`
- Установка с асинхронными библиотеками (без lxml):
    ```commandline
    pip install anime-parsers-ru[async]
    ```

Установка lxml вручную:
```commandline
pip install lxml
```

# Инструкция к парсерам

## Оглавление
- [Kodik инструкция](#kodik-инструкция)
- [AnimeGO инструкция](#animego-инструкция)
- [JutSu инструкция](#jutsu-инструкция)
- [Shikimori инструкция](#shikimori-инструкция)
- [Типы Исключений](#типы-исключений)

## Kodik инструкция

> [!IMPORTANT]
> Если вы хотите использовать функции библиотеки для апи кодика, то вся документация расположена в файле [KODIK_API.md](KODIK_API.md) 

> [!WARNING]
> Токен получаемый с помощью функции `get_token` НЕ работает для функций base_search, base_search_by_id, get_list и search
> По умолчанию данная функция не используется и класс требует от пользователя указать корректный токен.
> Если вы хотите использовать ограниченный функционал библиотеки, то можете при инициализации указать параметры 
> `token=KodikParser.get_token(), validate_token=False` (Для асинхронного параметр `token=KodikParserAsync.get_token_sync()`)

> [!TIP]
> В большинстве случаев в комментариях к функциям описаны шаблоны и возможные значения возвращаемых данных

0. Установите и импортируйте библиотеку
    
    Стандартно:
    ```commandline
    pip install anime-parsers-ru
    ```
    С lxml:
    ```commandline
    pip install anime-parsers-ru[lxml]
    ```
    ```python
    from anime_parsers_ru import KodikParser

    parser = KodikParser(<ваш api ключ>)
    ```

    __Для асинхронного кода__:
    ```commandline
    pip install anime-parsers-ru[async]
    ```
    (Установка без lxml)
    ```python
    from anime_parsers_ru import KodikParserAsync

    parser = KodikParserAsync(<ваш api ключ>)
    ```
    Для асинхронного парсера, после окончания работы следует вызвать метод
    ```python
    parser.close_async_session()
    ```
    Иначе выйдет ошибка о незакрытой сессии


> [!IMPORTANT]
> Если у вас нет токена для кодика, то оставьте параметр token при инициализации равным None. Парсер попробует получить токен автоматически.
> После получения токена, настоятельно рекомендуется сохранить этот токен и, для избегания задержек на получение токена и проверки, при следующей инициализации парсера, указать этот токен.
> Как это работает вы можете прочитать здесь: [TOKENS.md](kdk_tokns/TOKENS.md)

Также, если при запросах вы получаете ошибку о недоступности кодика в вашем регионе, можете при инициализации указать параметр proxy="http://host:port" для проксирования всех запросов к кодику. (Также поддерживается socks5)

1. Поиск аниме по названию
    ```python
    parser.search(title="Наруто", limit=None, include_material_data=True, anime_status=None, strict=False, only_anime=False) # список словарей
    # title - Название аниме/фильма/сериала
    # limit - количество результатов выдачи (int) (результатов будет сильно меньше чем указанное число, так как в выдаче результаты повторяются)
    # include_material_data - Добавлять дополнительные данные об элементе
    # anime_status - Статус выхода аниме (доступно: released, ongoing, None - если ищется не аниме или любой статус)
    # strict - Исключение названий далеких от оригинального
    # only_anime - возвращать только элементы где type in ['anime', 'anime-serial']
    ```
    Возвращает:
    ```json
    [
    {
        "title": "Название",
        "type": "тип мультимедиа (anime, film, ...)",
        "year": "Год выпуска фильма",
        "screenshots": [
            "ссылки на скриншоты"
        ],
        "shikimori_id": "Id шикимори, если нет - None",
        "kinopoisk_id": "Id кинопоиска, если нет - None",
        "imdb_id": "Id imdb, если нет - None",
        "worldart_link": "ссылка на worldart, если нет - None",
        "additional_data": {
            "Здесь будут находится все остальные данные выданные кодиком, не связанные с отдельным переводом"
        },
        "material_data": { 
            "Здесь будут все данные о сериале имеющиеся у кодика. (None если указан параметр include_material_data=False)
            В том числе оценки на шикимори, статус выхода, даты анонсов, выхода, все возможные названия, жанры, студии и многое другое."
        },
        "link": "ссылка на kodikplayer.com (Пример: //kodikplayer.com/video/20609/e8fd5bc1190b7eb1ee1a3e1c3aec5f62/720p)"
    },
    ]
    ```

2. Поиск аниме по id
    ```python
    parser.search_by_id(id="20", id_type="shikimori", limit=None)
    # id - id аниме на одном из сайтов
    # id_type - с какого сайта id (возможные: shikimori, kinopoisk, imdb, mdl, kodik, worldart_animation, worldart_cinema) (Для кодика нужно указывать в формате: serial-1234 / movie-1234)
    # limit - количество результатов выдачи (int) (результатов будет сильно меньше чем указанное число, так как в выдаче результаты повторяются)
    ```
    Параметр include_material_data включен по умолчанию. Если нужно использовать функцию без данного параметра, воспользуйтесь `base_search_by_id`
    Возвращает:
    ```json
    [
    {
        "title": "Название",
        "type": "тип мультимедиа (anime, film, ...)",
        "year": "Год выпуска фильма",
        "screenshots": [
            "ссылки на скриншоты"
        ],
        "shikimori_id": "Id шикимори, если нет - None",
        "kinopoisk_id": "Id кинопоиска, если нет - None",
        "imdb_id": "Id imdb, если нет - None",
        "worldart_link": "ссылка на worldart, если нет - None",
        "additional_data": {
            "Здесь будут находится все остальные данные выданные кодиком, не связанные с отдельным переводом"
        },
        "material_data": { 
            "Здесь будут все данные о сериале имеющиеся у кодика. (None если указан параметр include_material_data=False)
            В том числе оценки на шикимори, статус выхода, даты анонсов, выхода, все возможные названия, жанры, студии и многое другое."
        },
        "link": "ссылка на kodikplayer.com (Пример: //kodikplayer.com/video/20609/e8fd5bc1190b7eb1ee1a3e1c3aec5f62/720p)"
    },
    ]
    ```

3. Получить список аниме
    ```python
    data = parser.get_list(limit_per_page=50, pages_to_parse=1, include_material_data=True, anime_status=None, only_anime=False, start_from=None)
    # limit_per_page - количество результатов на одной странице (итоговых результатов будет сильно меньше чем указан параметр)
    # pages_to_parse - количество страниц для обработки (каждая страница - отдельный запрос)
    # include_material_data - включить в результат дополнительные данные
    # anime_status - Статус выхода аниме (доступно: released, ongoing, None - если ищется не аниме или любой статус)
    # only_anime - возвращать только элементы где type in ['anime', 'anime-serial']
    # start_from - начать поиск со страницы под id (id возвращается вторым элементом результата функции)
    ```
    Возвращает:
    ```json
    {
        [
        {
            "title": "Название",
            "type": "тип мультимедиа (anime, film, ...)",
            "year": "Год выпуска фильма",
            "screenshots": [
                "ссылки на скриншоты"
            ],
            "shikimori_id": "Id шикимори, если нет - None",
            "kinopoisk_id": "Id кинопоиска, если нет - None",
            "imdb_id": "Id imdb, если нет - None",
            "worldart_link": "ссылка на worldart, если нет - None",
            "additional_data": {
                "Здесь будут находится все остальные данные выданные кодиком, не связанные с отдельным переводом"
            },
            "material_data": { 
                "Здесь будут все данные о сериале имеющиеся у кодика. (None если указан параметр include_material_data=False)
                В том числе оценки на шикимори, статус выхода, даты анонсов, выхода, все возможные названия, жанры, студии и многое другое."
            },
            "link": "ссылка на kodikplayer.com (Пример: //kodikplayer.com/video/20609/e8fd5bc1190b7eb1ee1a3e1c3aec5f62/720p)"
        },
        ],
        "next_page_id": "id следующей страницы (для последовательного парсинга нескольких страниц) (может быть None, если след. страниц нет)"
    }
    ```

4. Получить информацию об аниме
    1. Через id
        ```python
        parser.get_info(id="z20", id_type="shikimori")
        # id - id аниме на одном из сайтов
        # id_type - с какого сайта id (возможные: shikimori, kinopoisk, imdb, mdl, kodik, worldart_animation, worldart_cinema) (Для кодика нужно указывать в формате: serial-1234 / movie-1234)
        ```
        Возвращает:
        ```json
        {
            "series_count": 220, 
            "translations": [
                {"id": "735", "type": "Озвучка", "name": "2x2 (220 эп.)", "series_range": [1, 220]}, 
                {"id": "609", "type": "Озвучка", "name": "AniDUB (220 эп.)", "series_range": [1, 220]}, 
                {"id": "869", "type": "Субтитры", "name": "Субтитры (220 эп.)", "series_range": [1, 220]}, 
                {"id": "958", "type": "Озвучка", "name": "AniRise (135 эп.)", "series_range": [1, 135]}, 
                {"id": "2550", "type": "Озвучка", "name": "ANI.OMNIA (8 эп.)", "series_range": [1, 8]}
            ]
        }
        ```
        series_range - тип tuple

        - Получить отдельно кол-во серий:
            ```python
            parser.series_count("z20", "shikimori") # число
            ```
        - Получить отдельно переводы:
            ```python
            parser.translations("z20", "shikimori") # список словарей
            ```
        
    2. Через embed ссылку 
        (работает быстрее, так как при запросе через id сначала происходит поиск embed ссылки и потом вызывается эта функция)
        ```python
        parser.get_info_from_embed(
            embed_link="url" # Пример embed ссылки: https://kodikplayer.com/serial/73959/68e2e57cb95f7fb93655637acaca26c2/720p
        )
        ```
        Возвращает те же данные что и через id

    
5. Прямая ссылка на видеофайл
    ```python
    parser.get_link(
        id="z20", 
        id_type="shikimori", 
        seria_num=1, 
        translation_id="609") # Кортеж
    # id - id медиа
    # id_type - тип id (возможные: shikimori, kinopoisk, imdb, mdl, kodik, worldart_animation, worldart_cinema) (Для кодика нужно указывать в формате: serial-1234 / movie-1234)
    # seria_num - номер серии (если фильм или одно видео - 0, также 0 корректен если есть нулевой эпизод)
    # translation_id - id перевода (прим: Anilibria = 610, если неизвестно - 0)
    ```
    Возвращает кортеж: `('//cloud.solodcdn.com/useruploads/67b6e546-...-4d8bfbedc2d7/d10...257:20...09/',720,[[0,90],[1280,1440]])`
    
    1. Ссылка
    Пример: `//cloud.solodcdn.com/useruploads/67b6e546-...-4d8bfbedc2d7/d10...257:20...09/`
    К данной ссылке в начале нужно добавить `http:` или `https:`, а в конце качество.mp4 (`720.mp4`) (Обычно доступны следующие варианты качества: `360`, `480`, `720`)
    2. Максимально возможное качество
    Прим: `720` (1280x720)
    3. Массив таймкодов начала и конца опенинга и эндинга (если таймкодов нет, пустой массив, если есть - то массив массивов (может быть как 1 фрагмент, так и несколько))
    Прим: `[[0, 90], [1150, 1300]]`. Где каждый массив это заставка (обычно первый - опенинг, второй - эндинг, но может быть и только один фрагмент), первое число в массиве начало фрагмента в секундах от начала файла, второе число - конец фрагмента в секундах с начала файла.

6. Ссылка на m3u8 плейлист
    ```python
    parser.get_m3u8_playlist_link(
        id="z20", 
        id_type="shikimori", 
        seria_num=1, 
        translation_id="609",
        quality=480) # Для "Наруто" нет 720p, хотя сервер и возвращает 720 в списке источников
    # id - id медиа
    # id_type - тип id (возможные: shikimori, kinopoisk, imdb)
    # seria_num - номер серии (если фильм или одно видео - 0, также 0 корректен если есть нулевой эпизод)
    # translation_id - id перевода (прим: Anilibria = 610, если неизвестно - 0)
    # quality - Желаемое качество (360, 480, 720). Если указанное качество будет больше, чем максимально доступное, вернется ссылка с максимально доступным качеством. По умолчанию: 720
    ```
    Возвращает строку вида:
    `https://cloud.solodcdn.com/useruploads/67b6e546-...-4d8bfbedc2d7/d10...257:20...09/480.mp4:hls:manifest.m3u8`

7. Текстовое содержание m3u8 плейлиста
    ```python
    parser.get_m3u8_playlist(
        id="z20", 
        id_type="shikimori", 
        seria_num=1, 
        translation_id="609",
        quality=480) # Для "Наруто" нет 720p, хотя сервер и возвращает 720 в списке источников
    # id - id медиа
    # id_type - тип id (возможные: shikimori, kinopoisk, imdb)
    # seria_num - номер серии (если фильм или одно видео - 0, также 0 корректен если есть нулевой эпизод)
    # translation_id - id перевода (прим: Anilibria = 610, если неизвестно - 0)
    # quality - Желаемое качество (360, 480, 720). Если указанное качество будет больше, чем максимально доступное, вернется ссылка с максимально доступным качеством. По умолчанию: 720
    ```
    Возвращает строку вида:
    ```
    #EXTM3U
    #EXT-X-TARGETDURATION:6
    #EXT-X-ALLOW-CACHE:YES
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-VERSION:3
    #EXT-X-MEDIA-SEQUENCE:1
    #EXTINF:6.000,
    https://.../480.mp4:hls:seg-1-v1-a1.ts
    #EXTINF:6.000,
    https://.../480.mp4:hls:seg-2-v1-a1.ts
    #EXTINF:6.000,
    https://.../480.mp4:hls:seg-3-v1-a1.ts
    ```

    Ключевое отличие от плейлиста который скачивается просто по ссылке (полученной в п.6) в том, что данная функция добавляет полную ссылку до сегментов. В изначальном файле ссылки содержатся в виде `./480.mp4...` что будет работать если ссылка открыта, например, в браузере, но не будет работать если файл открыт локально. С добавлением полной ссылки можно сохранить файл локально и запускать любым плеером который поддерживает m3u8 плейлисты (например VLC).

8. Получение расписания выхода
    Скорее всего синхронизируется с шикимори с периодом синхронизации 1-3 часа. Не требуется Api ключ.
    Для синхронного варианта:
    ```python
    parser.get_calendar(
        proxy="http://{host}:{port}" # Не обязательный параметр
    )
    # Или (без инициализации экземпляра)
    KodikParser.get_calendar(
        proxy="http://{host}:{port}" # Не обязательный параметр
    )
    ```
    Для асинхронного варианта:
    ```python
    await parser.get_calendar()
    ```
    Возвращает список словарей вида:
    ```json
    [
        {
        "aired_on": "YYYY-mm-dd",
        "anime": {"id": "shikimori id",
                    "image": {"original": "ссылка на оригинальный постер на шикимори (jpeg)",
                            "preview": "ссылка на превью постера на шикимори (webp)",
                            "x24": "ссылка на уменьшенную версию постера на шикимори (webp)",
                            "x48": "ссылка на уменьшенную версию постера на шикимори (webp)",
                            "x96": "ссылка на уменьшенную версию постера на шикимори (webp)"},
                    "name": "Оригинальное название",
                    "russian": "Русское название"},
        "duration": 0,
        "episodes": 8,
        "episodes_aired": 0,
        "kind": "тип аниме (movie, tv, ...)",
        "next_episode": 1,
        "next_episode_at": "YYYY-mm-ddTHH:MM:SSZ",
        "released_on": "YYYY-mm-dd",
        "score": 0.0,
        "status": "статус (anons, ongoing)"
        },
        ...
    ]
    ```

9. Получить embed ссылку
    ```python
    parser.get_embed_link(
        id="z20", # id медиа
        id_type="shikimori", # тип id (возможные: shikimori, kinopoisk, imdb, mdl, kodik, worldart_animation, worldart_cinema) (Для кодика нужно указывать в формате: serial-1234 / movie-1234)
        https=True, # устанавливает будет ли в полученной ссылке https:// или http:// (По умолчанию True)
    )
    ```
    Возвращает ссылку. Пример:
    `https://kodikplayer.com/serial/73959/68e2e57cb95f7fb93655637acaca26c2/720p`

    Данную ссылку можно использовать в iframe, чтобы добавить плеер кодика на сайт.

> [!IMPORTANT]
> В случае, если аниме является фильмом или содержит только одну серию, в параметр `seria_num` указывается значение `0`. В случае если перевод/субтитры неизвестны или нет выбора, в параметр `translation_id` указывается значение `"0"`

9. Прямое обращение к апи кодика
    Рекомендуется использовать модули KodikSearch и KodikList для обращения к апи.
    ```python
    parser.api_request (
        endpoint="list",
        filters={
            "limit": 5
        },
        parameters={
            "with_episodes_data": True
        }
    )
    # endpoint - ссылка куда направляется запрос (доступно: "search", "list", "translations")
    # filters - фильтры запроса
    # parameters - дополнительные параметры (для удобства можно их записывать в один словарь с фильтрами)
    ```
    Возвращает необработанный ответ от сервера кодика.
    Для подробного списка фильтров, параметров и примеров смотрите [инструкцию](KODIK_API.md).


> [!IMPORTANT]
> Если при попытке получения токена будет отловлено исключение по SSL сертификату, то будет попытка получения без валидации сертификата и библиотека requests будет писать в консоль предупреждения. Для асинхронной версии функции нет возможности отключить валидацию на достаточном уровне, поэтому будет выходить исключение о необходимости использовать синхронный вариант.

10. Получить токен
    ```python
    parser.get_token() # строка
    # Или
    KodikParser.get_token()
    ```
    Как это работает вы можете прочитать здесь: [TOKENS.md](kdk_tokns/TOKENS.md)

## AnimeGO инструкция
0. Установите и импортируйте библиотеку
    ```commandline
    pip install anime-parsers-ru
    ```
    ```python
    from anime_parsers_ru import AnimegoParser

    parser = AnimegoParser(
        mirror="домен зеркало", # Не обязательный параметр, по умолчанию None
        proxy="`http://host:port` или 'socks5://user:pass@host:port'", # Не обязательный параметр, по умолчанию None
        use_lxml=False, # Использовать ли lxml парсер (требуется отдельная установка), по умолчанию False
        use_cache=True, # Использовать ли кэш для страниц плееров (рекомендуется использовать), по умолчанию True
        cache_maxsize=300, # Максимальное количество объектов в кэше, по умолчанию 300
        cache_ttl=36000, # Срок жизни кэша в секундах, по умолчанию 36000 (10 часов)
    )
    ```

1. Поиск по сайту
    ```python
    parser.search(
        query="Название"
    )
    ```
    Возвращает список словарей вида:
    ```json
    [
        {
            "link": "Ссылка на страницу аниме",
            "id": "Числовой ID аниме на animego.org",
            "slug": "slug-из-url (прим: naruto-shippuuden)",
            "title": "Название аниме",
            "original_title": "Оригинальное название (если есть, иначе None)",
            "image": "Ссылка на постер (если есть, иначе None)",
            "rating": "Оценка аниме (если есть, иначе None)"
        },
        ...
    ]
    ```

2. Информация об аниме
    ```python
    parser.anime_info(
        url="ссылка", # Ссылка на страницу аниме. Прим: https://animego.me/anime/kulinarnye-skitaniya-v-parallelnom-mire-2239
    )
    ```
    Возвращает словарь вида:
    Некоторые поля могут отсутствовать на странице аниме и в таком случае их значение будет установлено в None
    ```json
    {
        "aired_at": "даты выхода",
        "anime_season": "аниме сезон",
        "author": "автор",
        "description": "Описание",
        "director": "Режиссёр",
        "duration": "длительность",
        "episodes": "эпизодов (если онгоинг, то вышло / всего)",
        "genres": ["список жанров"],
        "image": "ссылка на картинку",
        "main_characters": [{"character": "Персонаж",
                            "voice_actor": "Актер озвучки в оригинале"}],
        "minimal_age": "минимальный возраст зрителя",
        "mpaa_rating": "рейтинг MPAA",
        "next_episode": "дата выхода следующего эпизода (если онгоинг)",
        "original_source": "первоисточник",
        "other_titles": "другие названия",
        "related": [{"image": "Ссылка на картинку",
                    "link": "Ссылка на animego",
                    "relation": "связь (предыстория, продолжение...)",
                    "title": "Название",
                    "type": "Тип",
                    "year": "Год выхода"}],
        "score": "Оценка на анимего",
        "screenshots": ["список ссылок на скриншоты"],
        "status": "Статус (Вышел, Онгоинг...)",
        "studio": "Студия анимации",
        "theme": "Тема",
        "title": "Название",
        "translations": ["Список студий озвучки"],
        "type": "Тип"
    }
    ```

3. Информация об эпизодах
    ```python
    parser.get_episodes_info(
        anime_id="id аниме", # Прим: 2239
    )
    ```
    Возвращает список словарей вида:
    ```json
    [
        {
            "air_date": "дата выхода",
            "is_released": false, // вышло или нет (bool),
            "seria": 1, // номер серии,
            "title": "Название серии (или --- если не указано)"
        }
    ]
    ```

4. Получить расписание аниме
    ```python
    parser.get_schedule()
    ```
    Возвращает словарь вида:
    ```json
    {
        "schedule": {
            "Понедельник": [
                {   "episode": "Номер эпизода",
                    "image": "Ссылка на картинку",
                    "link": "Ссылка на аниме на animego",
                    "time": "Время выхода",
                    "title": "Название"
                },
                ...
            ],
            "Вторник": ...
        },
        "schedule_dates": {
            "Понедельник": "дата (либо: Сегодня, Завтра)",
            "Вторник": // ...
        }
    }
    ```

5. Обновления аниме
    (Новые озвучки на сайте)
    ```python
    parser.get_anime_updates()
    ```
    Возвращает список словарей вида:
    ```json
    [
        {
            "episode": "номер эпизода",
            "image": "Ссылка на картинку",
            "link": "Ссылка на аниме на animego",
            "time": "Время", // Время когда озвучка была добавлена на сайт
            "title": "Название",
            "translation": "Студия озвучки/субтитры"
        },
        ...
    ]
    ```

6. Получить аниме из текущего сезона
    ```python
    parser.get_anime_from_current_season()
    ```
    Возвращает список словарей вида:
    ```json
    {   
        "image": "Ссылка на картинку",
        "link": "Ссылка на аниме на animego",
        "title": "Название",
        "other_title": "Оригинальное название",
        "score": "Оценка"
    },
    ```

7. Получить id из ссылки (staticmethod)
    ```python
    AnimegoParser.get_id_from_link(
        link="ссылка" # Ссылка на страницу аниме. Пример: https://animego.me/anime/kulinarnye-skitaniya-v-parallelnom-mire-2239 
    )
    ```
    Возвращает строку:
    ```python
    '2239' # Для ссылки: https://animego.me/anime/kulinarnye-skitaniya-v-parallelnom-mire-2239
    ```

8. Получить список доступных озвучек и эпизодов
    Общее число эпизодов возвращается только при запросе первого эпизода!
    Для эпизодов больше 1, если не включен кэш, могут быть задержки.
    ```python
    parser.get_voices(
        anime_id="id аниме", # Прим: '2239'
        episode=1, # Номер эпизода
    )
    ```
    Возвращает словарь вида:
    ```json
    {
        "voices": [
            {
                "label": "Название озвучки",
                "translation_id": "ID для передачи в aniboom_get_stream_for_voice()",
                "player": "Тип плеера (kodik, aniboom, cvh, ...)",
                "embed": "Ссылка на embed",
                "cvh_id": "id для получения плейлиста CVH (только для cvh-плеера, иначе None)"
            },
            ...
        ],
        "total_episodes": 12 // None если не удалось определить или не первая серия
    }
    ```

9. Получить поток aniboom для определенной озвучки
    ```python
    parser.aniboom_get_stream_for_voice(
        translation_id="id перевода", # translation_id из функции get_voices
        episode=1, # Номер эпизода
        anime_id='id аниме' # Прим: '2239'
    )
    ```
    Возвращает словарь вида:
    ```json
    {
        "url": "https://.../.mpd", // или "https://.../.m3u8"
        "content": "Содержимое файла"
    }
    ```

10. Получить поток aniboom через embed ссылку
    ```python
    parser.aniboom_get_stream(
        embed_url="embed ссылка" # Embed ссылка из функции get_voices
    )
    ```
    Два варианта ответа:
    * Для MPD (приоритетный формат)
        ```json
        {
            "content": "<содержимое MPD-файла с абсолютными URL сегментов>",
            "kind": "MPD"
        }
        ```
    * Для HLS (если mpd не доступен)
        ```json
        {
            "url": "https://.../.m3u8",
            "kind": "HLS"
        }
        ```
11. Получить cvh плейлист
    Получает список эпизодов для указанного cvh_id
    ```python
    parser.cvh_get_playlist(
        cvh_id="cvh_id", # Из функции get_voices
    )
    ```
    Возвращает словарь вида:
    ```json
    {
        1: { // Номер сезона
            1: [ // Номер серии
                {
                    "cvh_id": "019d...11",
                    "episode": 1, // Номер эпизода
                    "season": 1, // Номер сезона
                    "name": "Название серии (обычно пустое)",
                    "vkId": "ID видео в системе CVH, нужен для получения ссылок на потоки через cvh_get_stream()",
                    "voiceStudio": "Название студии озвучки (напр. AnilibriaTV)",
                    "voiceType": "Тип озвучки/субтитры"
                }
            ]
        }
    }
    ```

12. Получить поток cvh
    Если уже известен vkId (например если до этого был сделан запрос на получение плейлиста), то рекомендуется использовать получение потока по vkId вместо данной функции для быстродействия.
    ```python
    parser.cvh_get_stream(
        cvh_id="cvh_id", # Из функции get_voices или cvh_get_playlist
        season=1, # Номер сезона (если будет найден только один сезон, данное значение будет проигнорировано)
        episode=1, # Номер эпизода
        translation="Название студии озвучки" # Прим: Anilibria.TV (может быть не точным, проводится fuzzy сравнение)
    )
    ```
    Возвращает словарь вида:
    ```json
    {
        "HLS": "https://.../.m3u8", // или None
        "DASH": "https://.../.mpd", // или None,
        "MP4s": ["https://.../360p.mp4", "https://.../720p.mp4"] // или []
    }
    ```

13. Получить поток cvh по vkId
    ```python
    parser.cvh_get_stream_by_id(
        vkId="ID видео в системе CVH" # Из функции cvh_get_playlist
    )
    ```
    Возвращает словарь вида:
    ```json
    {
        "HLS": "https://.../.m3u8", // или None
        "DASH": "https://.../.mpd", // или None,
        "MP4s": ["https://.../360p.mp4", "https://.../720p.mp4"] // или []
    }
    ```

## JutSu инструкция
0. Установите и импортируйте библиотеку
    ```commandline
    pip install anime-parsers-ru
    ```
    ```python
    from anime_parsers_ru import JutsuParser

    parser = JutsuParser()
    # Если вы знаете что есть актуальное зеркало сайта, можете указать его домен в параметре `mirror` при инициализации класса
    ```

Также в параметрах инициализации класса доступен параметр proxy (`http://host:port` или `socks5://user:pass@host:port`) для проксирования запросов на сервер

1. Данные по аниме (по ссылке на страницу)
    ```python
    parser.get_anime_info("Ссылка на страницу")
    # Пример ссылки: https://jut.su/tondemo-skill/
    # Для аниме: Кулинарные скитания в параллельном мире
    ```
    Возвращает словарь:
    ```json
    {
        "title": "Название аниме",
        "origin_title": "Оригинальное название (транслит японского названия на английском)",
        "age_rating": "Возрастное ограничение",
        "description": "Описание",
        "years": ["Год выхода 1 сезона", "Год выхода 2 сезона"],
        "genres": ["Жанр 1", "Жанр 2"],
        "poster": "Ссылка на картинку (плохое качество)",
        "seasons": [
            [ // 1 сезон будет обязательно, даже если у аниме нет других сезонов
                "ссылка на 1 серию 1 сезона (страница с плеером)",
                "ссылка на 2 серию 1 сезона (страница с плеером)"
            ],
            [ // 2 сезон если есть
                "ссылка на 1 серию 2 сезона (страница с плеером)",
                "ссылка на 2 серию 2 сезона (страница с плеером)"
            ],
        ],
        "seasons_names": [ // Если у аниме только 1 сезон, этот список будет пустым
            "Название 1 сезона", 
            "Название 2 сезона"
        ],
        "films": [ // Если фильмов нет - список пустой
            "Ссылка на фильм 1 (страница с плеером)",
            "Ссылка на фильм 2 (страница с плеером)",
        ]
    }
    ```

2. Получить ссылку на mp4 файл
    ```python
    parser.get_mp4_link('ссылка на страницу с плеером')
    # Пример ссылки: https://jut.su/tondemo-skill/episode-1.html
    # Еще пример ссылки: https://jut.su/ookami-to-koshinryou/season-1/episode-1.html
    ```
    Возвращает словарь:
    ```json
    {
        "360": "ссылка на mp4 файл с качеством 360p",
    }
    ```

> [!IMPORTANT]
> Для разных аниме разное количество доступных качеств плеера. (Например для "Наруто" доступно только 360 и 480, для большинства новых аниме доступно качество до 1080)
> Также jutsu не позволяет выбрать озвучку для аниме.

> [!NOTE]
> Для jutsu нет функции поиска, потому что он использует поиск яндекса по сайту и из-за того что он "умный" он может работать абсолютно непредсказуемо.
> В качестве "поиска" вы можете использовать оригинальное название аниме. Так как ссылка формируется по следующей схеме:
> Название аниме: Волчица и пряности
> Оригинальное название: Ookami to Koushinryou
> Ссылка на страницу: https://jut.su/ookami-to-koshinryou/

## Shikimori инструкция
0. Установите и импортируйте библиотеку
    ```commandline
    pip install anime-parsers-ru
    ```
    ```python
    from anime_parsers_ru import ShikimoriParser

    parser = ShikimoriParser(
        use_lxml=False, # Использовать lxml для парсинга html (нужно отдельно устанавливать) по умолчанию False
        mirror=None, # В случае, если оригинальный домен заблокирован, можно использовать этот параметр, чтобы заменить адрес сайта на зеркало. Пример: "1234.net". По умолчанию None
        proxy=None, # http или socks5 прокси (`http://host:port` или `socks5://user:pass@host:port`) по умолчанию None
        graphql_mirror="shikimori.io" # Зеркало для graphql (по умолчанию shikimori.io), если не указано, то будет использоваться shikimori.one (или общее зеркало, если указано)
    )
    ```
    __Для асинхронного кода__:
    ```commandline
    pip install anime-parsers-ru[async]
    ```
    ```python
    from anime_parsers_ru import ShikimoriParserAsync

    parser = ShikimoriParserAsync(
        use_lxml=False, # Использовать lxml для парсинга html (нужно отдельно устанавливать) по умолчанию False
        mirror=None, # В случае, если оригинальный домен заблокирован, можно использовать этот параметр, чтобы заменить адрес сайта на зеркало. Пример: "1234.net". По умолчанию None
        proxy=None, # http или socks5 прокси (`http://host:port` или `socks5://user:pass@host:port`) по умолчанию None
        graphql_mirror="shikimori.io" # Зеркало для graphql (по умолчанию shikimori.io), если не указано, то будет использоваться shikimori.one (или общее зеркало, если указано)
    )
    # Далее перед всеми функциями дополнительно нужно прописывать await
    ```
    Для асинхронного парсера, после окончания работы следует вызвать метод
    ```python
    parser.close_async_session()
    ```
    Иначе выйдет ошибка о незакрытой сессии

> [!NOTE]
> Шикимори ограничивает частоту запросов на сервер.
> Если шикимори возвращает код ответа 429, парсер вернет exception TooManyRequests.
> Для избежания этой ошибки делайте задержку 1-5 секунд между запросами.

Также в параметрах инициализации класса доступен параметр proxy (`http://host:port` или `socks5://user:pass@host:port` для проксирования запросов на сервер)

1. Поиск аниме по названию
    ```python
    parser.search('Название аниме')
    ```
    Возвращает список словарей:
    ```json
    [
        {
            "genres": ["Жанр1", "Жанр2"],
            "link": "Ссылка на страницу аниме",
            "original_title": "Оригинальное название (транслит японского названия на английском)",
            "poster": "Ссылка на постер к аниме (плохое качество) (если есть, иначе None)",
            "shikimori_id": "id шикимори",
            "status": "статус (вышло, онгоинг, анонс) (если есть, иначе None)",
            "studio": "студия анимации (если есть, иначе None)",
            "title": "Название",
            "type": "тип аниме (TV сериал, OVA, ONA, ...) (если есть, иначе None)",
            "year": "год выхода (если есть, иначе None)"
        }
    ]
    ```

2. Информация об аниме
    ```python
    parser.anime_info('shikimori_link')
    # Ссылку на шикимори можно получить с помощью функции
    # parser.link_by_id
    ```
    Возвращает словарь:
    ```json
    {
        "dates": "Даты выхода",
        "description": "Описание",
        "episode_duration": "Средняя продолжительность серии",
        "episodes": "Количество эпизодов если статус 'вышло' или 'вышедших эпизодов / анонсировано эпизодов' или None (если фильм)",
        "genres": ["Жанр1", "Жанр2"],
        "licensed": "Кто лицензировал в РФ или None",
        "licensed_in_ru": "Название аниме как лицензировано в РФ или None",
        "next_episode": "Дата выхода следующего эпизода или None",
        "original_title": "Оригинальное название",
        "picture": "Ссылка на jpeg постер",
        "premiere_in_ru": "Дата премьеры в РФ или None",
        "rating": "возрастной рейтинг",
        "score": "оценка на шикимори",
        "status": "статус выхода",
        "studio": "студия анимации",
        "themes": ["Тема1", "Тема2"],
        "title": "Название на русском",
        "type": "тип аниме (TV Сериал, Фильм, т.п.)"
    }
    ```

3. Дополнительная информация об аниме (связанные аниме (продолжения, предыстории), авторы, главные персонажи, скриншоты, видео, похожие аниме)
    ```python
    parser.additional_anime_info('Ссылка на страницу шикимори')
    # прим: https://shikimori.one/animes/z20-naruto
    ```
    Возвращает словарь:
    ```json
    {
        "related": [
            {
                "date": "Даты выхода/сезон",
                "name": "Название",
                "picture": "Ссылка на картинку",
                "relation": "тип связи (продолжение, предыстория, адаптация и т.п.)",
                "type": "Тип (TV сериал, OVA, ONA, манга, ранобэ и т.д.)",
                "url": "Ссылка на страницу шикимори"
            }
        ],
        "staff": [
            {
                "name": "Имя человека (на русском)",
                "roles": ["Роль1", "Роль2"],
                "link": "ссылка шикимори на человека"
            }
        ],
        "main_characters": [
            {
                "name": "Имя персонажа",
                "picture": "Картинка (jpeg)"
            }
        ],
        "screenshots": ["Ссылка на скриншот 1", "Ссылка на скриншот 2"],
        "videos": [
            {
                "name": "Название видео",
                "link": "Ссылка на видео (обычно ютуб)"
            }
        ],
        "similar": [
            {
                "name": "Название аниме (похожего)",
                "picture": "Картинка (постер)",
                "link": "Ссылка на шикимори"
            }
        ]
    }
    ```

4. Получить список аниме с шикимори по фильтрам
    ```python
    parser.get_anime_list(status=['статус аниме1', 'статус аниме2'], anime_type=['тип аниме1', 'тип аниме2'], rating='возрастной рейтинг', genres=['Жанр1', 'Жанр2'], start_page='начальная страница', page_limit='количество страниц для парсинга', sort_by='принцип сортировки')
    ```
    Доступные фильтры:
    - status - текущие статусы выхода (указывается строками в списке) (по умолчанию пусто (не учитывается в фильтрах)). Для исключения статуса из выдачи нужно указать перед ним восклицательный знак (!статус)
        <details>
        <summary>Список доступных статусов</summary>
        
        - ongoing - онгоинг
        - anons - анонс
        - released - вышло
        - latest - вышло недавно
        </details>
    - anime_type - типы аниме (указывается строками в списке) (по умолчанию пусто (не учитывается в фильтрах)). Для исключения типа из выдачи нужно указать перед ним восклицательный знак (!тип)
        <details>
        <summary>Список доступных типов</summary>
        
        - tv - ТВ Сериал
            - tv_13 - ТВ Сериал 12 серий (да, там tv_13, не опечатка, хз почему)
            - tv_24 - ТВ Сериал 24 серии
            - tv_48 - ТВ Сериал 48+ серий
        - movie - Фильм
        - ova - OVA
        - ona - ONA
        - special - спецвыпуск
        - tv_special - TV спецвыпуск
        - music - клип
        - pv - проморолик
        - cm - реклама
        </details>
    - rating - возрастной рейтинг (можно указать несколько значений в списке или одно строкой) (по умолчанию пустой список (не учитывается в фильтрах)). Для исключения возрастного рейтинга из выдачи нужно указать перед ним восклицательный знак (!рейтинг)
        <details>
        <summary>Список доступных возрастных рейтингов</summary>
        
        - g - нет возрастного ограничения
        - pg - рекомендуется присутствие родителей
        - pg_13 - детям до 13 просмотр не желателен
        - r - Лицам до 17 лет обязательно присутствие взрослого
        - r_plus - Лицам до 17 лет просмотр запрещен
        
        (Рейтинг rx - доступен только с аккаунтом (т.к. 18+) для поиска по такому рейтингу воспользуйтесь функцией deep_anime_search (описано ниже))
        </details>
    - genres - Список жанров и тем аниме (указывается строками в списке) (по умолчанию пусто (не учитывается в фильтрах)). Для исключения жанра/темы из выдачи нужно указать перед ним восклицательный знак (!статус)
        Можно указывать как английский вариант (с цифрами в начале), так и русский вариант.
        Список доступных жанров и тем можно получить в переменных genres_list и genres_list_ru (индексы жанров/тем из списка genres_list_ru соответствуют английским вариантам в списке genres_list)
        <details>
        <summary>Список тем/жанров</summary>
        Английский:
        ```json
        ["1-Action", "2-Adventure", "3-Racing", "4-Comedy", "5-Avant-Garde", "6-Mythology", "7-Mystery", "8-Drama", "9-Ecchi", "10-Fantasy", "11-Strategy-Game", "13-Historical", "14-Horror", "15-Kids", "17-Martial-Arts", "18-Mecha", "19-Music", "20-Parody", "21-Samurai", "22-Romance", "23-School", "24-Sci-Fi", "25-Shoujo", "27-Shounen", "29-Space", "30-Sports", "31-Super-Power", "32-Vampire", "35-Harem", "36-Slice-of-Life", "37-Supernatural", "38-Military", "39-Detective", "40-Psychological", "42-Seinen", "43-Josei", "102-Team-Sports", "103-Video-Game", "104-Adult-Cast", "105-Gore", "106-Reincarnation", "107-Love-Polygon", "108-Visual-Arts", "111-Time-Travel", "112-Gag-Humor", "114-Award-Winning", "117-Suspense", "118-Combat-Sports", "119-CGDCT", "124-Mahou-Shoujo", "125-Reverse-Harem", "130-Isekai", "131-Delinquents", "134-Childcare", "135-Magical-Sex-Shift", "136-Showbiz", "137-Otaku-Culture", "138-Organized-Crime", "139-Workplace", "140-Iyashikei", "141-Survival", "142-Performing-Arts", "143-Anthropomorphic", "144-Crossdressing", "145-Idols-(Female)", "146-High-Stakes-Game", "147-Medical", "148-Pets", "149-Educational", "150-Idols-(Male)", "151-Romantic-Subtext", "543-Gourmet"]
        ```
        Русский:
        ```json
        ["Экшен", "Приключения", "Гонки", "Комедия", "Авангард", "Мифология", "Тайна", "Драма", "Этти", "Фэнтези", "Стратегические игры", "Исторический", "Ужасы", "Детское", "Боевые искусства", "Меха", "Музыка", "Пародия", "Самураи", "Романтика", "Школа", "Фантастика", "Сёдзё", "Сёнен", "Космос", "Спорт", "Супер сила", "Вампиры", "Гарем", "Повседневность", "Сверхъестественное", "Военное", "Детектив", "Психологическое", "Сэйнэн", "Дзёсей", "Командный спорт", "Видеоигры", "Взрослые персонажи", "Жестокость", "Реинкарнация", "Любовный многоугольник", "Изобразительное искусство", "Путешествие во времени", "Гэг-юмор", "Удостоено наград", "Триллер", "Спортивные единоборства", "CGDCT", "Махо-сёдзё", "Реверс-гарем", "Исэкай", "Хулиганы", "Забота о детях", "Магическая смена пола", "Шоу-бизнес", "Культура отаку",  "Организованная преступность", "Работа", "Иясикэй", "Выживание", "Исполнительское искусство", "Антропоморфизм", "Кроссдрессинг", "Идолы (Жен.)", "Игра с высокими ставками", "Медицина", "Питомцы", "Образовательное", "Идолы (Муж.)", "Романтический подтекст", "Гурман"]
        ```
        </details>
    - season - Сезон и год (указывается строками в списке) (по умолчанию пустой список (не учитывается в фильтрах)). Для исключения сезона из выдачи нужно указать перед ним восклицательный знак (!сезон)
        [!] Отсутствует валидация данных.
        Значения формируются следующим образом: <время года>_<год>. Пример: `winter_2026`
        Данный формат доступен только на текущий, следующий и предыдущий год.
        Для более ранних лет следует указывать только год. Пример: `2023`. Также можно указывать только год и для текущего, следующего и предыдущего года.
        Более ранние периоды:
        * 00-е - `200x`
        * 90-е - `199x`
        * 80-е - `198x`
        * 70-е - `197x`
        * До 1980 - `ancient`
    - duration - длительность серии (можно указать несколько значений в списке или одно строкой) (по умолчанию пустой список (не учитывается в фильтрах)). Для исключения длительности серии из выдачи нужно указать перед ним восклицательный знак (!рейтинг)
        <details>
        <summary>Список доступных длительностей</summary>
        
        - S - Меньше 10 минут
        - D - 10 - 30 минут
        - F - Больше 30 минут
        
        </details>
    - origin - первоисточник (указывается строками в списке) (по умолчанию пустой список (не учитывается в фильтрах)). Для исключения первоисточника из выдачи нужно указать перед ним восклицательный знак (!источник)
        Можно указывать как английский, так и русский вариант.
        Список доступных первоисточников можно получить в переменных origins_list и origins_list_ru (индексы первоисточников из списка origins_list_ru соответствуют английским вариантам в списке origins_list)
        
        <details>
        <summary>Список доступных первоисточников</summary>
        Английский:
        ```json
        ["original", "manga", "web_manga", "four_koma_manga", "light_novel", "novel", "web_novel", "visual_novel", "game", "card_game", "book", "picture_book", "radio", "music", "mixed_media", "other"]
        ```
        Русский:
        ```json
        ["Оригинал", "Манга", "Веб-манга", "Ёнкома", "Ранобэ", "Роман", "Веб-новелла", "Визуальная новелла", "Игра", "Карточная игра", "Книга", "Книга с картинками", "Радио", "Музыка", "Более одного", "Другое"]
        ```
        </details>
    - studios - студии анимации (указывается строками в списке) (по умолчанию пустой список (не учитывается в фильтрах)). Для исключения первоисточника из выдачи нужно указать перед ним восклицательный знак (!студия)
        [!] Отсутствует валидация данных.
        Посмотреть актуальный список можно на шикимори или воспользоваться списком ниже (возможно не полный).
        Для корректной работы следует указывать полную строку (с числами).
        <details>
        <summary>Список студий (может быть не актуальным)</summary>
        ```json
        ["1-Studio-Pierrot", "10-Production-I.G", "103-Tatsunoko-Production", "11-Madhouse", "111-NHK", "112-Brain's-Base", "13-Studio-4°C", "14-Sunrise", "150-Sanrio", "18-Toei-Animation", "2-Kyoto-Animation", "200-Tezuka-Productions", "207-Magic-Bus", "218-Zexcs", "22-Nippon-Animation", "242-Ashi-Productions", "247-Shin-Ei-Animation", "27-Xebec", "28-OLM", "291-CoMix-Wave-Films", "3-Gonzo", "300-SILVER-LINK.", "36-Gallop", "37-Studio-Deen", "38-Arms", "4-Bones", "41-Satelight", "44-Shaft", "48-AIC", "56-A-1-Pictures", "569-MAPPA", "6-Gainax", "65-Tokyo-Movie-Shinsha", "68-Mushi-Production", "7-J.C.Staff", "73-TMS-Entertainment", "858-Wit-Studio", "86-Group-TAC", "91-feel.", "95-Doga-Kobo"]
        ```
        </details>
    - licensed - лицензия (указывается строками в списке) (по умолчанию пустой список (не учитывается в фильтрах)). Для исключения лицензии из выдачи нужно указать перед ней восклицательный знак (!лицензия)
        [!] Отсутствует валидация данных.
        Посмотреть актуальный список можно на шикимори или воспользоваться списком ниже (возможно не полный).
        Для корректной работы следует указывать полную строку (плюсы заменяют пробелы).
        <details>
        <summary>Список студий (может быть не актуальным)</summary>
        ```json
        ["any", "Crunchyroll", "Wakanim", "DEEP", "Netflix", "2x2", "FAN", "MC+Entertainment", "VK", "Амедиатека", "CLS+Media", "Русский+Репортаж", "Reanimedia", "Ракета+Релизинг", "Иви", "Пионер", "Мега-Аниме", "Кинологистика", "RUSCICO", "Экспонента", "Cinema+Prestige", "XL+Media", "RWV", "Вольга", "Первый+ТВЧ", "Централ+Партнершип"]
        ```
        </details>
    - rating_from - оценка на Шикимори от включительнно (целое число от 0 до 10) (по умолчанию отсутствует (не учитывается в фильтрах))
    - rating_to - оценка на Шикимори до включительно (целое число от 0 до 10) (по умолчанию отсутствует (не учитывается в фильтрах))
    - start_page - начальная страница (начиная с 1) (по умолчанию 1)
    - page_limit - какое количество страниц парсить (по умолчанию 3)
    - sort_by - тип сортировки (по умолчанию rating) (одно значение строкой)
        <details>
        <summary>Список доступных сортировок</summary>
        
        - rating - по рэйтингу
        - popularity - по популярности
        - name - по алфавиту
        - aired_on - по дате выхода
        - ranked_random - случайно
        - id_desc - по id шикимори
        </details>

    [!] Если один из переданных параметров будет неверным (не содержится в списке доступных) - программа автоматически пропустит его.

    Возвращает список словарей:
    ```json
    {
        "original_title": "Оригинальное название (на английском)",
        "poster": "Ссылка на картинку-постер",
        "shikimori_id": "id шикимори",
        "title": "Название на русском",
        "type": "Тип аниме (ТВ Сериал, ONA, ...)",
        "url": "Ссылка на страницу аниме",
        "year": "год выхода аниме"
    }
    ```

5. Получение онгоингов со страницы /ongoings
    ```python
    parser.get_ongoing_calendar()
    ```
    Возвращает:
    ```json
    "<день недели>, <число> <месяц>": [
        {
            "episode": "номер эпизода (число) если не анонс и не релиз, иначе None",
            "id": "Shikimori id",
            "link": "Ссылка на страницу тайтла",
            "name_en": "Английское название",
            "name_ru": "Русское название",
            "picture": "Ссылка на картинку",
            "release_type": "тип релиза: анонс или релиз (или другое) если episode == None, иначе None",
            "time": "Расчетное время релиза (оригинала)"
        },
    ]
    ```

6. Вспомогательные функции
    - Ссылка на страницу шикимори по id
        ```python
        parser.link_by_id('shikimori_id')
        ```
        Возвращает ссылку
        (id: 53446 результат: https://shikimori.one/animes/53446-tondemo-skill-de-isekai-hourou-meshi)
    - Id по ссылке на шикимори
        ```python
        parser.id_by_link('ссылка на страницу')
        ```
        Возвращает shikimori_id
        (ссылка: https://shikimori.one/animes/53446-tondemo-skill-de-isekai-hourou-meshi id: 53446)

7. Поиск аниме и информации по аниме через псевдо api shikimori
    Данные функции используют предоставленную shikimori тестовую функцию для api. (https://shikimori.one/api/doc/graphql)
    Подробные примеры запросов и ответов вы можете посмотреть в файле [SHIKI_API.md](https://github.com/YaNesyTortiK/AnimeParsers/blob/main/SHIKI_API.md)
    
    - Поиск аниме
        ```python
        parser.deep_search(
            title='Название аниме', 
            search_parameters={'поисковый параметр 1': 'значение поискового параметра 1'},
            return_parameters=['Параметр результата 1', 'параметр результата 2']
        )
        ```
        Возвращает список словарей
    
    - Информация об аниме по id
        ```python
        parser.deep_anime_info(
            shikimori_id='id шикимори',
            return_parameters=['Параметр результата 1', 'параметр результата 2']
        )
        ```
        Возвращает словарь

## Типы исключений
В данной библиотеке добавлены следующие исключения:

- TokenError
    Обозначает неверный или отсутствующий токен в тех функциях где он требуется

- ServiceError
    Обозначает ошибку сервера. Если сервер не вернул один из ожидаемых кодов или, если нет ожидаемых, не вернул код 200

- PostArgumentError
    Обозначает ошибкув данных или их отсутсвие при передаче на сервер (обычно посредством POST запроса)

- NoResults
    Обозначает отсутсвие результатов

- UnexpectedBehaviour
    Обозначает непредвиденное поведение или ошибку, код-статус которой не был ожидаемым. (В некоторых случаях заменяет ServiceError)

- QualityNotFound
    Обозначает что запрашиваемое качество видео не найдено

- AgeRestricted
    Обозначает возрастную блокировку (требуется авторизация для доступа к этим данным)

- TooManyRequests
    Обозначает http статус 429. То есть сервер заблокировал запрос из-за слишком частого обращения

- ContentBlocked
    Обозначает что запрашиваемый контент или плеер заблокирован/недоступен

- ServiceIsOverloaded
    Обозначает http статус 520. То есть сервер перегружен и не может ответить на запрос

- DecryptionFailure
    При попытке дешифровать ссылку от Kodik возникла ошибка
