# anicli-api
Программный интерфейс набора парсеров аниме с различных источников.
Присутствует поддержка sync и async методов с помощью `httpx` библиотеки.
Парсеры работают на REST-API (если у источника есть доступ) или если такой интерфейс
отсутствует, то с помощью parsel, chompjs, jmespath, regex библиотек.
# install
`pip install anicli-api`
# Overview
Структура проекта
- source - наборы модулей для извлечения информации об аниме тайтлов из источников
- player - наборы модулей для извлечения прямой ссылки на видео
Подробнее про `source` и `player` смотрите ниже.
```
anicli_api
├── base.py - базовый класс модуля-парсера
├── _http.py - предварительно сконфигурированные классы httpx.Client и httpx.AsyncClient
├── _logger.py - логгер
├── player - модули получения ссылок на видео
│ ├── __template__.py - шаблон модуля PlayerExtractor
│ ├── ... ready-made модули
│ ...
├── source - модули парсеров с источников
│ ├── parsers/... автоматически сгенерированные парсеры html страниц
│ ├── __template__.py - шаблон для экстрактора
│ ├─ ... ready-made парсеры
│ ...
└── tools - прочие модули
```
Схематичный принцип работы модуля из директории `source`
префикс `a_` обозначает асинхронный метод, возвращаемые объекты идентичны
```mermaid
flowchart TD
E[Extractor] -->|"search('QUERY') | a_search('QUERY')"| S("List[Search]")
E -->|"ongoing() | a_ongoing()"| O("List[Ongoing]")
O -->|"get_anime() | a_get_anime()"| A[Anime]
S -->|"get_anime() | a_get_anime()"| A
A -->|"get_episodes() | a_get_episodes()"|Ep["List[Episode]"]
Ep -->|"get_sources() | a_get_sources()"|So["List[Source]"]
So -->|"get_videos() | a_get_videos()"|V["List[Video]"]
```
# quickstart
```python
from anicli_api.source.animego import Extractor
from anicli_api.tools import cli
if __name__ == '__main__':
cli(Extractor())
```
> Этот модуль реализован для простого ручного тестирования парсеров и "имитирует" потенциальное настоящее приложение
Пример своей реализации
```python
from anicli_api.source.animego import Extractor # can usage any source
def _print_to_rows(items):
print(*[f"{i}) {r}" for i, r in enumerate(items)], sep="\n")
if __name__ == "__main__":
ex = Extractor()
print("PRESS CTRL + C for exit app")
while True:
results = ex.search(input("search query > "))
if not results:
print("Not founded, try again")
continue
_print_to_rows(results)
anime = results[int(input("anime > "))].get_anime()
print(anime)
episodes = anime.get_episodes()
_print_to_rows(episodes)
episode = episodes[int(input("episode > "))]
sources = episode.get_sources()
_print_to_rows(sources)
source = sources[int(input("source > "))]
videos = source.get_videos()
_print_to_rows(videos)
video = videos[int(input("video > "))]
print(video.type, video.quality, video.url, video.headers)
```
С asyncio аналогично, но **все** методы получения объектов имеют префикс `a_`:
```python
import asyncio
from anicli_api.source.animego import Extractor # или любой другой источник
async def main():
ex = Extractor()
prompt = input("search query > ")
# a_ - async prefix.
# simular in Ongoing, Anime, Episode, Source, Video objects
results = await ex.a_search(prompt)
print(*[f"{i}) {r}" for i, r in enumerate(results)], sep="\n")
if __name__ == '__main__':
asyncio.run(main())
```
# Player
Эти модули можно использовать как экстрактор прямых ссылок на видео
> Эти модули минимально реализуют получение ссылок на видео с минимальными метаданными и заголовками для скачивания и
> не стремятся стать заменой yt-dlp
```python
import asyncio
from anicli_api.player.sibnet import SibNet
async def main():
videos = await SibNet().a_parse(URL)
print(*videos)
if __name__ == '__main__':
URL = 'https://video.sibnet.ru/shell.php?videoid=432356'
print(*SibNet().parse(URL))
# asyncio support!
asyncio.run(main())
```
# source description
- name - имя модуля
- type - тип источника получения данных.
- **NO** - неофициальный (парсинг html документов и запросы недокументированным API методам)
- **YES** - официальный (rest-api)
- note - примечания
- dubbers - тип озвучек.
- many - от различных авторов.
- subtitles - только субтитры.
- once - один вид (случайный)
- author - своя
| name | url | official api | dubbers | note |
|--------------------------------|----------------------------|--------------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| animego | https://animego.org | NO | many | источники kodik, animego, не работает на IP отличных от СНГ и стран прибалтики |
| animania DROP (dead) | https://animania.online | NO | many | источник kodik, не работает на IP отличных от СНГ и стран прибалтики |
| sovetromantica | https://sovetromantica.com | NO | subtitles, author | не на все тайтлы есть видео, у себя хостят |
| anilibria | https://anilibria.tv | YES | author | |
| animevost | https://animevost.org | YES | author | |
| jutsu | https://jut.su | NO | once | Запуск видео в сторонних плеерах зависим от используемого user-agent заголовка в API интерфейсе. Некоторые тайтлы заблокированы на территории РФ |
| sameband | https://sameband.studio | NO | author | |
| animego.pro | https://animego.pro | NO | many | Нестабильный uptime сайта (могут быть проблемы с доступом) |
# players description
> Требует дополнения и дополнительные тесты
- name - имя плеера
- max quality - максимальное разрешение выдаваемое источником. Это может быть 0 (аудио, без видео), 144, 240, 360, 480, 720, 1080
- note - примечания
| name | max quality | note |
|----------------|--------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| kodik | 720 (на старых тайтлах (ранние One Peace, Evangelion) - 480) | **работает только на IP СНГ и стран прибалтики** |
| aniboom | 1080 | **работает только на IP СНГ и стран прибалтики**. Иногда не возвращает mpd ссылку на видео |
| sibnet | 480 | |
| animejoy | 1080 | только актуальные ongoing, потом видео удаляются с серверов |
| csst | 1080 | |
| dzen | 1080 | |
| mailru | | |
| okru | | |
| sovetromantica | 1080 | не на все тайтлы присутствуют видео |
| vkcom | 1080 (какого качества автор зальет видео) | CDN сервера в РФ, в других странах загружается медленнее |
| nuum | 1080 | проект от wasd.tv |
| anilibria | 1080 | |
| jutsu | 1080 | |
| sameband | 1080 | |
## logging
Настройка логгера идет через ключ `anicli-api`
```python
import logging
logger = logging.getLogger('anicli-api')
```
## http path
### source
Если по какой-то либо причине вас не устраивают настройки по умолчанию - то вы можете задать
конфигурацию http клиентов для экстракторов. Или если необходимо подключить proxy
```python
from anicli_api.source.animego import Extractor
import httpx
# не обязательно настраивать все клиенты, зависит от режима использования
# например, если вы будете использовать только asyncio - настраивайте только http_async_client
my_client = httpx.Client(headers={"user-agent": "007"}, proxies="http://127.0.0.1:8080")
my_async_client = httpx.AsyncClient(headers={"user-agent": "007"}, proxies="http://127.0.0.1:8080")
# настройки клиентов будут передаваться всем объектам кроме методов Source.get_videos()
# и Source.a_get_videos()
ex = Extractor(http_client=my_client, http_async_client=my_async_client)
# изменение http клиента для объекта
results = ex.search("lain")
result = results[0]
result.http = my_client
result.http_async = my_async_client
...
```
### player
В player для модификации httpx клиентов (Client, AsyncioClient) необходимо передать kwargs аргументы:
```python
from anicli_api.source.animego import Extractor
sources = (
Extractor()
.search("lain")[0]
.get_anime()
.get_episodes()[0]
.get_sources()
)
videos = sources[0].get_videos(transport=None, # reset to default httpx.HTTPTransport
headers={"User-Agent": "i'm crushing :("})
```
## Структуры объектов
Приведены поля, которые **гарантированно** возвращаются в API интерфейсе библиотеки.
В некоторых источниках могут присутствовать дополнительные поля или атрибуты для
использования во внутренних методах.
- Например, в `anilibria` и `animevost` поля почти идентичны ответам API.
В `animego.Anime` есть сырой несериализованный `raw_json` для извлечения дополнительных метаданных.
- В некоторых источниках на полях могут присутствовать "заглушки" для поддержания консистентности API интерфейса. Например,
в модуле `anicli_api.source.jutsu.Episode` уже можно получить прямые ссылки на видео (Video объект),
но для поддержания полиморфизма, необходимо возвращать объект `Source` и только потом `Video`
- Если по какой-либо причине объекты не получены (ddos защита, региональные ограничения) - то возвращает пустой список.
(#TODO возможно, необходимо выбрасывать исключение?)
### Search
- url: str - URL на тайтл
- title: str - имя найденного тайтла
- thumbnail: str - изображение
### Ongoing
- url: str - URL на тайтл
- title: str - имя найденного тайтла
- thumbnail: str - изображение
### Anime
- title: str - имя тайтла (на русском)
- thumbnail: str - изображение
- description: Optional[str] - описание тайтла. может вернуть пустую строку или None
### Episode
- title: str - имя эпизода (Если источник его не хранит, то будет Серия или Serie)
- num: str - номер эпизода
### Source
- url: str - ссылка на источник
- title: str - даббер или имя источника
### Video
Объект `Video`, полученный из `Source.get_video`/`Source.a_get_video`
имеет следующую структуру:
* type - тип видео (m3u8, mp4, mpd, audio)
* quality - разрешение видео (0, 144, 240, 360, 480, 720, 1080)
* url - прямая ссылка на видео
* headers - заголовки требуемые для получения потока.
Если возвращает пустой словарь - заголовки не нужны
# Примечания
- Парсеры из директории
[anicli_api/source/parsers](anicli_api/source/parsers) автоматически генерируются с помощью
[ssc_gen](https://github.com/vypivshiy/selector_schema_codegen),
настройки хранятся в [libanime_schema](https://github.com/libanime/libanime_schema)
- Для модификаций парсеров из директории `anicli_api/source/parsers`
используйте наследование, чтобы не потерять изменения при перегенерации библиотекой `ssc_gen`.
- Проект разработан преимущественно на личное, некоммерческое использование с client-side
стороны. Проекта не несет ответственности за поломки, убытки и решение
предоставляется "Как есть" в соответствии с [MIT](LIENSE) лицензией.
- Основная цель этого проекта — связать автоматизацию и эффективность извлечения того,
что предоставляется пользователю в Интернете.
Весь контент, доступный в рамках проекта, размещается на внешних неаффилированных источниках.
- **Этот проект не включает инструменты кеширования и сохранения всех полученных данных,
только готовые реализации парсеров и программные интерфейсы**
Raw data
{
"_id": null,
"home_page": null,
"name": "anicli_api",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "anime, api, ru, russia, asyncio, parser, httpx, dev",
"author": "vypivshiy",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/db/f6/b53611d560cc5fc268ac337d401e3d96d420e0d1e3d1bd58fcadce659e6b/anicli_api-0.7.0.tar.gz",
"platform": null,
"description": "# anicli-api\n\n\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0431\u043e\u0440\u0430 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0430\u043d\u0438\u043c\u0435 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432.\n\n\u041f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 sync \u0438 async \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e `httpx` \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.\n\n\u041f\u0430\u0440\u0441\u0435\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430 REST-API (\u0435\u0441\u043b\u0438 \u0443 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f) \u0438\u043b\u0438 \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\n\u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e parsel, chompjs, jmespath, regex \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a. \n\n\n# install\n`pip install anicli-api`\n\n# Overview\n\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\n\n- source - \u043d\u0430\u0431\u043e\u0440\u044b \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0430\u043d\u0438\u043c\u0435 \u0442\u0430\u0439\u0442\u043b\u043e\u0432 \u0438\u0437 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432\n- player - \u043d\u0430\u0431\u043e\u0440\u044b \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u044f\u043c\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\n\n\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e `source` \u0438 `player` \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0438\u0436\u0435.\n\n```\nanicli_api\n\u251c\u2500\u2500 base.py - \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0443\u043b\u044f-\u043f\u0430\u0440\u0441\u0435\u0440\u0430\n\u251c\u2500\u2500 _http.py - \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b httpx.Client \u0438 httpx.AsyncClient\n\u251c\u2500\u2500 _logger.py - \u043b\u043e\u0433\u0433\u0435\u0440\n\u251c\u2500\u2500 player - \u043c\u043e\u0434\u0443\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\n\u2502 \u251c\u2500\u2500 __template__.py - \u0448\u0430\u0431\u043b\u043e\u043d \u043c\u043e\u0434\u0443\u043b\u044f PlayerExtractor\n\u2502 \u251c\u2500\u2500 ... ready-made \u043c\u043e\u0434\u0443\u043b\u0438\n\u2502 ...\n\u251c\u2500\u2500 source - \u043c\u043e\u0434\u0443\u043b\u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0441 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432\n\u2502 \u251c\u2500\u2500 parsers/... \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0441\u0435\u0440\u044b html \u0441\u0442\u0440\u0430\u043d\u0438\u0446\n\u2502 \u251c\u2500\u2500 __template__.py - \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u044d\u043a\u0441\u0442\u0440\u0430\u043a\u0442\u043e\u0440\u0430\n\u2502 \u251c\u2500 ... ready-made \u043f\u0430\u0440\u0441\u0435\u0440\u044b\n\u2502 ...\n\u2514\u2500\u2500 tools - \u043f\u0440\u043e\u0447\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438\n\n```\n\n\u0421\u0445\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u043e\u0434\u0443\u043b\u044f \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 `source`\n\n\u043f\u0440\u0435\u0444\u0438\u043a\u0441 `a_` \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b \n\n```mermaid\nflowchart TD\n E[Extractor] -->|\"search('QUERY') | a_search('QUERY')\"| S(\"List[Search]\")\n E -->|\"ongoing() | a_ongoing()\"| O(\"List[Ongoing]\")\n \n O -->|\"get_anime() | a_get_anime()\"| A[Anime]\n S -->|\"get_anime() | a_get_anime()\"| A\n \n A -->|\"get_episodes() | a_get_episodes()\"|Ep[\"List[Episode]\"]\n Ep -->|\"get_sources() | a_get_sources()\"|So[\"List[Source]\"]\n So -->|\"get_videos() | a_get_videos()\"|V[\"List[Video]\"]\n\n```\n# quickstart\n\n```python\nfrom anicli_api.source.animego import Extractor\nfrom anicli_api.tools import cli\n\nif __name__ == '__main__':\n cli(Extractor())\n```\n\n> \u042d\u0442\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0438 \"\u0438\u043c\u0438\u0442\u0438\u0440\u0443\u0435\u0442\" \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\n\n\n\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\n\n```python\nfrom anicli_api.source.animego import Extractor # can usage any source\n\n\ndef _print_to_rows(items):\n print(*[f\"{i}) {r}\" for i, r in enumerate(items)], sep=\"\\n\")\n\n\nif __name__ == \"__main__\":\n ex = Extractor()\n print(\"PRESS CTRL + C for exit app\")\n while True:\n results = ex.search(input(\"search query > \"))\n if not results:\n print(\"Not founded, try again\")\n continue\n _print_to_rows(results)\n\n anime = results[int(input(\"anime > \"))].get_anime()\n print(anime)\n\n episodes = anime.get_episodes()\n _print_to_rows(episodes)\n episode = episodes[int(input(\"episode > \"))]\n\n sources = episode.get_sources()\n _print_to_rows(sources)\n source = sources[int(input(\"source > \"))]\n\n videos = source.get_videos()\n _print_to_rows(videos)\n video = videos[int(input(\"video > \"))]\n print(video.type, video.quality, video.url, video.headers)\n```\n\n\u0421 asyncio \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u043d\u043e **\u0432\u0441\u0435** \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438\u043c\u0435\u044e\u0442 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 `a_`:\n\n```python\nimport asyncio\nfrom anicli_api.source.animego import Extractor # \u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\n\nasync def main():\n ex = Extractor()\n prompt = input(\"search query > \")\n # a_ - async prefix.\n # simular in Ongoing, Anime, Episode, Source, Video objects\n results = await ex.a_search(prompt) \n print(*[f\"{i}) {r}\" for i, r in enumerate(results)], sep=\"\\n\")\n \nif __name__ == '__main__':\n asyncio.run(main())\n```\n\n# Player\n\n\u042d\u0442\u0438 \u043c\u043e\u0434\u0443\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u044d\u043a\u0441\u0442\u0440\u0430\u043a\u0442\u043e\u0440 \u043f\u0440\u044f\u043c\u044b\u0445 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\n\n> \u042d\u0442\u0438 \u043c\u043e\u0434\u0443\u043b\u0438 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0438 \n> \u043d\u0435 \u0441\u0442\u0440\u0435\u043c\u044f\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u043d\u043e\u0439 yt-dlp\n\n```python\nimport asyncio\n\nfrom anicli_api.player.sibnet import SibNet\n\nasync def main():\n videos = await SibNet().a_parse(URL)\n print(*videos)\n \n \nif __name__ == '__main__':\n URL = 'https://video.sibnet.ru/shell.php?videoid=432356'\n print(*SibNet().parse(URL))\n # asyncio support!\n asyncio.run(main())\n```\n\n# source description\n\n- name - \u0438\u043c\u044f \u043c\u043e\u0434\u0443\u043b\u044f\n- type - \u0442\u0438\u043f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.\n - **NO** - \u043d\u0435\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 (\u043f\u0430\u0440\u0441\u0438\u043d\u0433 html \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c API \u043c\u0435\u0442\u043e\u0434\u0430\u043c) \n - **YES** - \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 (rest-api)\n- note - \u043f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f\n- dubbers - \u0442\u0438\u043f \u043e\u0437\u0432\u0443\u0447\u0435\u043a. \n - many - \u043e\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0430\u0432\u0442\u043e\u0440\u043e\u0432. \n - subtitles - \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b. \n - once - \u043e\u0434\u0438\u043d \u0432\u0438\u0434 (\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439)\n - author - \u0441\u0432\u043e\u044f\n\n| name | url | official api | dubbers | note |\n|--------------------------------|----------------------------|--------------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|\n| animego | https://animego.org | NO | many | \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 kodik, animego, \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 IP \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0442 \u0421\u041d\u0413 \u0438 \u0441\u0442\u0440\u0430\u043d \u043f\u0440\u0438\u0431\u0430\u043b\u0442\u0438\u043a\u0438 |\n| animania DROP (dead) | https://animania.online | NO | many | \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a kodik, \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 IP \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0442 \u0421\u041d\u0413 \u0438 \u0441\u0442\u0440\u0430\u043d \u043f\u0440\u0438\u0431\u0430\u043b\u0442\u0438\u043a\u0438 |\n| sovetromantica | https://sovetromantica.com | NO | subtitles, author | \u043d\u0435 \u043d\u0430 \u0432\u0441\u0435 \u0442\u0430\u0439\u0442\u043b\u044b \u0435\u0441\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u0443 \u0441\u0435\u0431\u044f \u0445\u043e\u0441\u0442\u044f\u0442 |\n| anilibria | https://anilibria.tv | YES | author | |\n| animevost | https://animevost.org | YES | author | |\n| jutsu | https://jut.su | NO | once | \u0417\u0430\u043f\u0443\u0441\u043a \u0432\u0438\u0434\u0435\u043e \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u043f\u043b\u0435\u0435\u0440\u0430\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c \u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0433\u043e user-agent \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0432 API \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0430\u0439\u0442\u043b\u044b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043d\u0430 \u0442\u0435\u0440\u0440\u0438\u0442\u043e\u0440\u0438\u0438 \u0420\u0424 |\n| sameband | https://sameband.studio | NO | author | |\n| animego.pro | https://animego.pro | NO | many | \u041d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 uptime \u0441\u0430\u0439\u0442\u0430 (\u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c) |\n\n\n# players description\n\n> \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b\n\n- name - \u0438\u043c\u044f \u043f\u043b\u0435\u0435\u0440\u0430\n- max quality - \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u044b\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c 0 (\u0430\u0443\u0434\u0438\u043e, \u0431\u0435\u0437 \u0432\u0438\u0434\u0435\u043e), 144, 240, 360, 480, 720, 1080\n- note - \u043f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f\n\n| name | max quality | note |\n|----------------|--------------------------------------------------------------|--------------------------------------------------------------------------------------------|\n| kodik | 720 (\u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0445 \u0442\u0430\u0439\u0442\u043b\u0430\u0445 (\u0440\u0430\u043d\u043d\u0438\u0435 One Peace, Evangelion) - 480) | **\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 IP \u0421\u041d\u0413 \u0438 \u0441\u0442\u0440\u0430\u043d \u043f\u0440\u0438\u0431\u0430\u043b\u0442\u0438\u043a\u0438** |\n| aniboom | 1080 | **\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 IP \u0421\u041d\u0413 \u0438 \u0441\u0442\u0440\u0430\u043d \u043f\u0440\u0438\u0431\u0430\u043b\u0442\u0438\u043a\u0438**. \u0418\u043d\u043e\u0433\u0434\u0430 \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 mpd \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e |\n| sibnet | 480 | |\n| animejoy | 1080 | \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 ongoing, \u043f\u043e\u0442\u043e\u043c \u0432\u0438\u0434\u0435\u043e \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 |\n| csst | 1080 | |\n| dzen | 1080 | |\n| mailru | | |\n| okru | | |\n| sovetromantica | 1080 | \u043d\u0435 \u043d\u0430 \u0432\u0441\u0435 \u0442\u0430\u0439\u0442\u043b\u044b \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432\u0438\u0434\u0435\u043e |\n| vkcom | 1080 (\u043a\u0430\u043a\u043e\u0433\u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0430\u0432\u0442\u043e\u0440 \u0437\u0430\u043b\u044c\u0435\u0442 \u0432\u0438\u0434\u0435\u043e) | CDN \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432 \u0420\u0424, \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0430\u0445 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 |\n| nuum | 1080 | \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0442 wasd.tv |\n| anilibria | 1080 | |\n| jutsu | 1080 | |\n| sameband | 1080 | |\n \n## logging\n\n\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043b\u043e\u0433\u0433\u0435\u0440\u0430 \u0438\u0434\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u044e\u0447 `anicli-api`\n\n```python\nimport logging\nlogger = logging.getLogger('anicli-api')\n```\n\n## http path\n\n### source\n\n\u0415\u0441\u043b\u0438 \u043f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043b\u0438\u0431\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0432\u0430\u0441 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e - \u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0430\u0442\u044c\n\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e http \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u044d\u043a\u0441\u0442\u0440\u0430\u043a\u0442\u043e\u0440\u043e\u0432. \u0418\u043b\u0438 \u0435\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c proxy\n\n```python\nfrom anicli_api.source.animego import Extractor\nimport httpx\n# \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b, \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0435\u0436\u0438\u043c\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f\n# \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e asyncio - \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e http_async_client \nmy_client = httpx.Client(headers={\"user-agent\": \"007\"}, proxies=\"http://127.0.0.1:8080\")\nmy_async_client = httpx.AsyncClient(headers={\"user-agent\": \"007\"}, proxies=\"http://127.0.0.1:8080\")\n\n# \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c \u043a\u0440\u043e\u043c\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 Source.get_videos() \n# \u0438 Source.a_get_videos()\n\nex = Extractor(http_client=my_client, http_async_client=my_async_client)\n\n# \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 http \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430\nresults = ex.search(\"lain\")\nresult = results[0]\nresult.http = my_client\nresult.http_async = my_async_client\n...\n\n```\n\n### player\n\n\u0412 player \u0434\u043b\u044f \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 httpx \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 (Client, AsyncioClient) \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c kwargs \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:\n\n```python\nfrom anicli_api.source.animego import Extractor\n\n\nsources = (\n Extractor()\n .search(\"lain\")[0]\n .get_anime()\n .get_episodes()[0]\n .get_sources()\n)\n\nvideos = sources[0].get_videos(transport=None, # reset to default httpx.HTTPTransport\n headers={\"User-Agent\": \"i'm crushing :(\"})\n```\n\n## \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432\n\n\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 **\u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e** \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 API \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \n\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u0445 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438\u043b\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0434\u043b\u044f \n\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u0430\u0445.\n\n- \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 `anilibria` \u0438 `animevost` \u043f\u043e\u043b\u044f \u043f\u043e\u0447\u0442\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b \u043e\u0442\u0432\u0435\u0442\u0430\u043c API. \n\u0412 `animego.Anime` \u0435\u0441\u0442\u044c \u0441\u044b\u0440\u043e\u0439 \u043d\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 `raw_json` \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.\n\n- \u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u0445 \u043d\u0430 \u043f\u043e\u043b\u044f\u0445 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \"\u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0438\" \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0438 API \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \n\u0432 \u043c\u043e\u0434\u0443\u043b\u0435 `anicli_api.source.jutsu.Episode` \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u044f\u043c\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e (Video \u043e\u0431\u044a\u0435\u043a\u0442),\n\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 `Source` \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c `Video`\n- \u0415\u0441\u043b\u0438 \u043f\u043e \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b (ddos \u0437\u0430\u0449\u0438\u0442\u0430, \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f) - \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a.\n (#TODO \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435?)\n\n### Search\n- url: str - URL \u043d\u0430 \u0442\u0430\u0439\u0442\u043b\n- title: str - \u0438\u043c\u044f \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0430\u0439\u0442\u043b\u0430\n- thumbnail: str - \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\n\n### Ongoing\n- url: str - URL \u043d\u0430 \u0442\u0430\u0439\u0442\u043b\n- title: str - \u0438\u043c\u044f \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0430\u0439\u0442\u043b\u0430\n- thumbnail: str - \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\n\n### Anime\n- title: str - \u0438\u043c\u044f \u0442\u0430\u0439\u0442\u043b\u0430 (\u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c)\n- thumbnail: str - \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\n- description: Optional[str] - \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0430\u0439\u0442\u043b\u0430. \u043c\u043e\u0436\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u043b\u0438 None\n\n### Episode\n- title: str - \u0438\u043c\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0430 (\u0415\u0441\u043b\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0435\u0433\u043e \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0421\u0435\u0440\u0438\u044f \u0438\u043b\u0438 Serie)\n- num: str - \u043d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430\n\n### Source\n- url: str - \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\n- title: str - \u0434\u0430\u0431\u0431\u0435\u0440 \u0438\u043b\u0438 \u0438\u043c\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\n\n### Video\n\n\u041e\u0431\u044a\u0435\u043a\u0442 `Video`, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0438\u0437 `Source.get_video`/`Source.a_get_video` \n\u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:\n\n* type - \u0442\u0438\u043f \u0432\u0438\u0434\u0435\u043e (m3u8, mp4, mpd, audio)\n* quality - \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e (0, 144, 240, 360, 480, 720, 1080)\n* url - \u043f\u0440\u044f\u043c\u0430\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0432\u0438\u0434\u0435\u043e\n* headers - \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430. \n\u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043b\u043e\u0432\u0430\u0440\u044c - \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b\n\n# \u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f\n\n- \u041f\u0430\u0440\u0441\u0435\u0440\u044b \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \n[anicli_api/source/parsers](anicli_api/source/parsers) \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \n[ssc_gen](https://github.com/vypivshiy/selector_schema_codegen), \n\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 [libanime_schema](https://github.com/libanime/libanime_schema)\n\n- \u0414\u043b\u044f \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 `anicli_api/source/parsers`\n\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 `ssc_gen`.\n\n\n- \u041f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430 \u043b\u0438\u0447\u043d\u043e\u0435, \u043d\u0435\u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 client-side \n\u0441\u0442\u043e\u0440\u043e\u043d\u044b. \u041f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0435 \u043d\u0435\u0441\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u043f\u043e\u043b\u043e\u043c\u043a\u0438, \u0443\u0431\u044b\u0442\u043a\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435\n\u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \"\u041a\u0430\u043a \u0435\u0441\u0442\u044c\" \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 [MIT](LIENSE) \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439.\n\n- \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u2014 \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \n\u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. \n\u0412\u0435\u0441\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043d\u0435\u0430\u0444\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u0445.\n\n- **\u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \n\u0442\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0441\u0435\u0440\u043e\u0432 \u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b**\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Anime extractors api implementation",
"version": "0.7.0",
"project_urls": {
"Bug Tracker": "https://github.com/vypivshiy/anicli-api/issues",
"Cli app": "https://github.com/vypivshiy/ani-cli-ru"
},
"split_keywords": [
"anime",
" api",
" ru",
" russia",
" asyncio",
" parser",
" httpx",
" dev"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f13c29fe52ea32f7674ab1eb9628de38a1202cf5a195389e97dff28e51ef267e",
"md5": "d7c03f0644b05c6717e147e12092e0a5",
"sha256": "b7d6e9f51f6cec0b1bb3e1263b81c4b4db7d431d7d9d0901a55c805c495fc0ec"
},
"downloads": -1,
"filename": "anicli_api-0.7.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d7c03f0644b05c6717e147e12092e0a5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 56388,
"upload_time": "2024-12-24T18:55:33",
"upload_time_iso_8601": "2024-12-24T18:55:33.120498Z",
"url": "https://files.pythonhosted.org/packages/f1/3c/29fe52ea32f7674ab1eb9628de38a1202cf5a195389e97dff28e51ef267e/anicli_api-0.7.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "dbf6b53611d560cc5fc268ac337d401e3d96d420e0d1e3d1bd58fcadce659e6b",
"md5": "b6058078d04ce7e42ca13a44076a2bef",
"sha256": "2f01dfc71c17c5c532d472897d85eeb33e306424d98d000231642962bf6df159"
},
"downloads": -1,
"filename": "anicli_api-0.7.0.tar.gz",
"has_sig": false,
"md5_digest": "b6058078d04ce7e42ca13a44076a2bef",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 44359,
"upload_time": "2024-12-24T18:55:35",
"upload_time_iso_8601": "2024-12-24T18:55:35.700856Z",
"url": "https://files.pythonhosted.org/packages/db/f6/b53611d560cc5fc268ac337d401e3d96d420e0d1e3d1bd58fcadce659e6b/anicli_api-0.7.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-24 18:55:35",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "vypivshiy",
"github_project": "anicli-api",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "anicli_api"
}