ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π½Π°Π±ΠΎΡΠ° ΠΏΠ°ΡΡΠ΅ΡΠΎΠ² Π°Π½ΠΈΠΌΠ΅ Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠΎΠ².
ΠΡΠΈΡΡΡΡΡΠ²ΡΠ΅Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° sync ΠΈ async ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² Ρ ΠΏΠΎΠΌΠΎΡΡΡ httpx
Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ.
ΠΠ°ΡΡΠ΅ΡΡ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π½Π° REST-API (Π΅ΡΠ»ΠΈ Ρ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ° Π΅ΡΡΡ Π΄ΠΎΡΡΡΠΏ) ΠΈΠ»ΠΈ Π΅ΡΠ»ΠΈ ΡΠ°ΠΊΠΎΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΎΡΡΡΡΡΡΠ²ΡΠ΅Ρ, ΡΠΎ Ρ ΠΏΠΎΠΌΠΎΡΡΡ parsel, chompjs, jmespath, regex Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ.
pip install anicli-api
Π‘ΡΡΡΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°
- 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_
ΠΎΠ±ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΠΉ ΠΌΠ΅ΡΠΎΠ΄, Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½Ρ
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]"]
from anicli_api.source.animego import Extractor
from anicli_api.tools import cli
if __name__ == '__main__':
cli(Extractor())
ΠΡΠΎΡ ΠΌΠΎΠ΄ΡΠ»Ρ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ Π΄Π»Ρ ΠΏΡΠΎΡΡΠΎΠ³ΠΎ ΡΡΡΠ½ΠΎΠ³ΠΎ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΏΠ°ΡΡΠ΅ΡΠΎΠ² ΠΈ "ΠΈΠΌΠΈΡΠΈΡΡΠ΅Ρ" ΠΏΠΎΡΠ΅Π½ΡΠΈΠ°Π»ΡΠ½ΠΎΠ΅ Π½Π°ΡΡΠΎΡΡΠ΅Π΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
ΠΡΠΈΠΌΠ΅Ρ ΡΠ²ΠΎΠ΅ΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ
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_
:
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())
ΠΡΠΈ ΠΌΠΎΠ΄ΡΠ»ΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊ ΡΠΊΡΡΡΠ°ΠΊΡΠΎΡ ΠΏΡΡΠΌΡΡ ΡΡΡΠ»ΠΎΠΊ Π½Π° Π²ΠΈΠ΄Π΅ΠΎ
ΠΡΠΈ ΠΌΠΎΠ΄ΡΠ»ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΡΡΡ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΡΡΠ»ΠΎΠΊ Π½Π° Π²ΠΈΠ΄Π΅ΠΎ Ρ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΠΌΠΈ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΠΌΠΈ ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°ΠΌΠΈ Π΄Π»Ρ ΡΠΊΠ°ΡΠΈΠ²Π°Π½ΠΈΡ ΠΈ Π½Π΅ ΡΡΡΠ΅ΠΌΡΡΡΡ ΡΡΠ°ΡΡ Π·Π°ΠΌΠ΅Π½ΠΎΠΉ yt-dlp
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())
- 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 ΠΎΡΠ»ΠΈΡΠ½ΡΡ ΠΎΡ Π‘ΠΠ ΠΈ ΡΡΡΠ°Π½ ΠΏΡΠΈΠ±Π°Π»ΡΠΈΠΊΠΈ. Π§Π°ΡΡΠΎ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ ΠΏΠΎΠ΄ Π ΠΠ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ |
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 | |
yummy-anime.org | https://yummy-anime.org | NO | many | |
yummy-anime.ru | https://yummy-anime.ru | YES | many |
Π’ΡΠ΅Π±ΡΠ΅Ρ Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ΅ΡΡΡ
- 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 ΡΡΡΠ»ΠΊΡ Π½Π° Π²ΠΈΠ΄Π΅ΠΎ |
askor | 1080 | |
sibnet | 480 | |
csst | 1080 | |
dzen | 1080 | |
mailru | ||
okru | ||
sovetromantica | 1080 | Π½Π΅ Π½Π° Π²ΡΠ΅ ΡΠ°ΠΉΡΠ»Ρ ΠΏΡΠΈΡΡΡΡΡΠ²ΡΡΡ Π²ΠΈΠ΄Π΅ΠΎ |
vkcom | 1080 (ΠΊΠ°ΠΊΠΎΠ³ΠΎ ΠΊΠ°ΡΠ΅ΡΡΠ²Π° Π°Π²ΡΠΎΡ Π·Π°Π»ΡΠ΅Ρ Π²ΠΈΠ΄Π΅ΠΎ) | CDN ΡΠ΅ΡΠ²Π΅ΡΠ° Π² Π Π€, Π² Π΄ΡΡΠ³ΠΈΡ ΡΡΡΠ°Π½Π°Ρ Π·Π°Π³ΡΡΠΆΠ°Π΅ΡΡΡ ΠΌΠ΅Π΄Π»Π΅Π½Π½Π΅Π΅ |
anilibria | 1080 | |
jutsu | 1080 | |
sameband | 1080 |
ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π»ΠΎΠ³Π³Π΅ΡΠ° ΠΈΠ΄Π΅Ρ ΡΠ΅ΡΠ΅Π· ΠΊΠ»ΡΡ anicli-api
import logging
logger = logging.getLogger('anicli-api')
ΠΠ°Π±ΠΎΡΡ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΡ ΠΌΠΎΠ΄ΡΠ»Π΅ΠΉ
ΠΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½Π°Ρ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΡ Π΄Π»Ρ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΡ cookie Π΄Π°Π½Π½ΡΡ ΠΈΠ· Π±ΡΠ°ΡΠ·Π΅ΡΠ° Π΄Π»Ρ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π² httpx. Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ rookiepy
pip install anicli-api[browser-cookies]
import httpx
from anicli_api.tools.cookies import get_raw_cookies_from_browser, raw_cookies_to_httpx_cookiejar
# ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅Ρ Π²ΡΠ΅ cookies
raw_cookies = get_raw_cookies_from_browser("firefox")
cookies = raw_cookies_to_httpx_cookiejar(raw_cookies)
# ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΡΠΉ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ host:
# raw_cookies = get_raw_cookies_from_browser("firefox", ["example.com"])
httpx.get("https://example.com", cookies=cookies)
# update cookies in extractors:
from anicli_api.source.yummy_anime_org import Extractor
ex = Extractor()
ex.http.cookies.update(cookies)
ex.http_async.cookies.update(cookies)
ΠΡΠΎΡΡΠΎΠΉ cli-ΠΊΠ»ΠΈΠ΅Π½Ρ Π΄Π»Ρ ΡΡΡΠ½ΡΡ ΡΠ΅ΡΡΠΎΠ² ΠΈ ΠΈΠΌΠΈΡΠ°ΡΠΈΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°
from anicli_api.tools.dummy_cli import cli
from anicli_api.source.yummy_anime_org import Extractor
cli(Extractor())
ΠΠ°Π±ΠΎΡΡ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΡ ΡΡΠ½ΠΊΡΠΈΠΉ Π΄Π»Ρ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Ρ ΡΠΊΡΡΡΠ°ΠΊΡΠΎΡΠ°ΠΌΠΈ
from anicli_api.source.yummy_anime_org import Extractor
from anicli_api.tools.helpers import get_video_by_quality, video_picker_iterator, async_video_picker_iterator
ex = Extractor()
result = ex.search('lain')[0]
anime = result.get_anime()
episodes = anime.get_episodes()
sources = episodes[0].get_sources()
videos = sources[0].get_videos()
# ΠΈΠ·Π²Π»Π΅ΡΡ Π±Π»ΠΈΠΆΠ°ΠΉΡΠ΅Π΅ Π΄ΠΎΡΡΡΠΏΠ½ΠΎΠ΅ ΠΏΠΎ ΠΊΠ°ΡΠ΅ΡΡΠ²Ρ Π²ΠΈΠ΄Π΅ΠΎ
# 1080 or linear quality: 720 -> 480 -> 360 -> 240...
video = get_video_by_quality(videos, 1080)
# ΠΈΡΠ΅ΡΠ°ΡΠΎΡ Π²ΠΈΠ΄Π΅ΠΎ ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°
# ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅Ρ Π²ΡΠ±ΡΠ°Π½Π½ΠΎΠ΅ Π²ΠΈΠ΄Π΅ΠΎ ΠΏΠΎ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΡ ΠΈ ΠΎΠ·Π²ΡΡΠΊΠ΅
for video_and_title in video_picker_iterator(
start_source=sources[0],
start_video=videos[0],
anime=anime,
episodes=episodes[3:]): # limit episodes to 3
v, title = video_and_title
print(title, v)
# async ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ°
async def main():
async for vid_and_title in async_video_picker_iterator(
start_source=sources[0],
start_video=videos[0],
anime=anime,
episodes=episodes[3:] # limit episodes to 3
):
v, title = vid_and_title
print(title, v)
import asyncio
asyncio.run(main())
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ m3u ΠΏΠ»Π΅ΠΉΠ»ΠΈΡΡΠ° ΠΈΠ· ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΡΠΊΡΡΡΠ°ΠΊΡΠΎΡΠ°
from anicli_api.source.yummy_anime_org import Extractor
from anicli_api.tools.m3u import generate_playlist, generate_asyncio_playlist
from anicli_api.tools.helpers import video_picker_iterator, async_video_picker_iterator
ex = Extractor()
result = ex.search('lain')[0]
anime = result.get_anime()
episodes = anime.get_episodes()
# get first source for first 3 episodes
sources = [e.get_sources()[0] for e in episodes[:3]]
videos = sources[0].get_videos()
# generate playlist from sources
playlist_sources = generate_playlist(sources)
# generate playlist from video_picker
video_objs, titles_objs = [],[]
for video_and_title in video_picker_iterator(
start_source=sources[0],
start_video=videos[0],
anime=anime,
episodes=episodes[3:]): # limit episodes to 3
v, title = video_and_title
video_objs.append(v)
titles_objs.append(title)
playlist = generate_playlist(video_objs, titles_objs)
# asyncio
# if target not Source object - you can use sync variant
import asyncio
playlist_async = asyncio.run(generate_asyncio_playlist(sources))
ΠΡΠ»ΠΈ ΠΏΠΎ ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ Π»ΠΈΠ±ΠΎ ΠΏΡΠΈΡΠΈΠ½Π΅ Π²Π°Ρ Π½Π΅ ΡΡΡΡΠ°ΠΈΠ²Π°ΡΡ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ - ΡΠΎ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π·Π°Π΄Π°ΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ http ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠ² Π΄Π»Ρ ΡΠΊΡΡΡΠ°ΠΊΡΠΎΡΠΎΠ². ΠΠ»ΠΈ Π΅ΡΠ»ΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ proxy
from anicli_api.source.animego import Extractor
import httpx
# Π½Π΅ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°ΡΡ Π²ΡΠ΅ ΠΊΠ»ΠΈΠ΅Π½ΡΡ, Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ ΡΠ΅ΠΆΠΈΠΌΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
# Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΅ΡΠ»ΠΈ Π²Ρ Π±ΡΠ΄Π΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ asyncio - Π½Π°ΡΡΡΠ°ΠΈΠ²Π°ΠΉΡΠ΅ ΡΠΎΠ»ΡΠΊΠΎ http_async_client
my_client = httpx.Client(headers={"user-agent": "007"}, proxy="http://127.0.0.1:8080")
my_async_client = httpx.AsyncClient(headers={"user-agent": "007"}, proxy="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 Π΄Π»Ρ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ httpx ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠ² (Client, AsyncioClient) Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ kwargs Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ:
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 Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π²ΡΠ±ΡΠ°ΡΡΠ²Π°ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅?)
- url: str - URL Π½Π° ΡΠ°ΠΉΡΠ»
- title: str - ΠΈΠΌΡ Π½Π°ΠΉΠ΄Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠ°ΠΉΡΠ»Π°
- thumbnail: str - ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅
- url: str - URL Π½Π° ΡΠ°ΠΉΡΠ»
- title: str - ΠΈΠΌΡ Π½Π°ΠΉΠ΄Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠ°ΠΉΡΠ»Π°
- thumbnail: str - ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅
- title: str - ΠΈΠΌΡ ΡΠ°ΠΉΡΠ»Π° (Π½Π° ΡΡΡΡΠΊΠΎΠΌ)
- thumbnail: str - ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅
- description: Optional[str] - ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΠ°ΠΉΡΠ»Π°. ΠΌΠΎΠΆΠ΅Ρ Π²Π΅ΡΠ½ΡΡΡ ΠΏΡΡΡΡΡ ΡΡΡΠΎΠΊΡ ΠΈΠ»ΠΈ None
- title: str - ΠΈΠΌΡ ΡΠΏΠΈΠ·ΠΎΠ΄Π° (ΠΡΠ»ΠΈ ΠΈΡΡΠΎΡΠ½ΠΈΠΊ Π΅Π³ΠΎ Π½Π΅ Ρ ΡΠ°Π½ΠΈΡ, ΡΠΎ Π±ΡΠ΄Π΅Ρ Π‘Π΅ΡΠΈΡ ΠΈΠ»ΠΈ Serie)
- num: str - Π½ΠΎΠΌΠ΅Ρ ΡΠΏΠΈΠ·ΠΎΠ΄Π°
- url: str - ΡΡΡΠ»ΠΊΠ° Π½Π° ΠΈΡΡΠΎΡΠ½ΠΈΠΊ
- title: str - Π΄Π°Π±Π±Π΅Ρ ΠΈΠ»ΠΈ ΠΈΠΌΡ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°
ΠΠ±ΡΠ΅ΠΊΡ 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 Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π³Π΅Π½Π΅ΡΠΈΡΡΡΡΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ssc_gen, Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ Ρ ΡΠ°Π½ΡΡΡΡ Π² libanime_schema
-
ΠΠ»Ρ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΈΠΉ ΠΏΠ°ΡΡΠ΅ΡΠΎΠ² ΠΈΠ· Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ
anicli_api/source/parsers
ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΠ΅, ΡΡΠΎΠ±Ρ Π½Π΅ ΠΏΠΎΡΠ΅ΡΡΡΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉssc_gen
. -
ΠΡΠΎΠ΅ΠΊΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎ Π½Π° Π»ΠΈΡΠ½ΠΎΠ΅, Π½Π΅ΠΊΠΎΠΌΠΌΠ΅ΡΡΠ΅ΡΠΊΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ client-side ΡΡΠΎΡΠΎΠ½Ρ. ΠΡΠΎΠ΅ΠΊΡΠ° Π½Π΅ Π½Π΅ΡΠ΅Ρ ΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎΡΡΠΈ Π·Π° ΠΏΠΎΠ»ΠΎΠΌΠΊΠΈ, ΡΠ±ΡΡΠΊΠΈ ΠΈ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ "ΠΠ°ΠΊ Π΅ΡΡΡ" Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΈΠΈ Ρ MIT Π»ΠΈΡΠ΅Π½Π·ΠΈΠ΅ΠΉ.
-
ΠΡΠ½ΠΎΠ²Π½Π°Ρ ΡΠ΅Π»Ρ ΡΡΠΎΠ³ΠΎ ΠΏΡΠΎΠ΅ΠΊΡΠ° β ΡΠ²ΡΠ·Π°ΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΡ ΠΈ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π² ΠΠ½ΡΠ΅ΡΠ½Π΅ΡΠ΅. ΠΠ΅ΡΡ ΠΊΠΎΠ½ΡΠ΅Π½Ρ, Π΄ΠΎΡΡΡΠΏΠ½ΡΠΉ Π² ΡΠ°ΠΌΠΊΠ°Ρ ΠΏΡΠΎΠ΅ΠΊΡΠ°, ΡΠ°Π·ΠΌΠ΅ΡΠ°Π΅ΡΡΡ Π½Π° Π²Π½Π΅ΡΠ½ΠΈΡ Π½Π΅Π°ΡΡΠΈΠ»ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°Ρ .
-
ΠΡΠΎΡ ΠΏΡΠΎΠ΅ΠΊΡ Π½Π΅ Π²ΠΊΠ»ΡΡΠ°Π΅Ρ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΈ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ Π²ΡΠ΅Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΡ Π΄Π°Π½Π½ΡΡ , ΡΠΎΠ»ΡΠΊΠΎ Π³ΠΎΡΠΎΠ²ΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΏΠ°ΡΡΠ΅ΡΠΎΠ² ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ