Добавление кэширования (#16)
This commit is contained in:
parent
03470a7402
commit
896f35327e
3 changed files with 57 additions and 28 deletions
14
README.md
14
README.md
|
|
@ -83,8 +83,8 @@ python3 main.py --session-id "<ID Сессии>" --url "https://music.yandex.ru/
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: main.py [-h] [--hq] [--skip-existing] [--add-lyrics] [--embed-cover]
|
usage: main.py [-h] [--hq] [--skip-existing] [--add-lyrics] [--embed-cover]
|
||||||
[--stick-to-artist] [--cover-resolution <Разрешение обложки>]
|
[--cover-resolution <Разрешение обложки>] [--delay <Задержка>]
|
||||||
[--delay <Задержка>] [--only-music] [--debug]
|
[--stick-to-artist] [--only-music] [--enable-caching]
|
||||||
(--artist-id <ID исполнителя> | --album-id <ID альбома> | --track-id <ID трека> | --playlist-id <владелец плейлиста>/<тип плейлиста> | -u URL)
|
(--artist-id <ID исполнителя> | --album-id <ID альбома> | --track-id <ID трека> | --playlist-id <владелец плейлиста>/<тип плейлиста> | -u URL)
|
||||||
[--unsafe-path] [--dir <Папка>] [--path-pattern <Паттерн>]
|
[--unsafe-path] [--dir <Папка>] [--path-pattern <Паттерн>]
|
||||||
--session-id <ID сессии> [--user-agent <User-Agent>]
|
--session-id <ID сессии> [--user-agent <User-Agent>]
|
||||||
|
|
@ -99,12 +99,16 @@ options:
|
||||||
--skip-existing Пропускать уже загруженные треки
|
--skip-existing Пропускать уже загруженные треки
|
||||||
--add-lyrics Загружать тексты песен
|
--add-lyrics Загружать тексты песен
|
||||||
--embed-cover Встраивать обложку в .mp3 файл
|
--embed-cover Встраивать обложку в .mp3 файл
|
||||||
--stick-to-artist Загружать только альбомы созданные данным исполнителем
|
|
||||||
--cover-resolution <Разрешение обложки>
|
--cover-resolution <Разрешение обложки>
|
||||||
по умолчанию: 400
|
по умолчанию: 400
|
||||||
--delay <Задержка> Задержка между запросами, в секундах (по умолчанию: 3)
|
--delay <Задержка> Задержка между запросами, в секундах (по умолчанию: 3)
|
||||||
--only-music Загружать только музыкальные альбомы
|
--stick-to-artist Загружать альбомы, созданные только данным
|
||||||
--debug Включить отладочный вывод
|
исполнителем
|
||||||
|
--only-music Загружать только музыкальные альбомы (пропускать
|
||||||
|
подкасты и аудиокниги)
|
||||||
|
--enable-caching Включить кэширование. Данная опция полезна при
|
||||||
|
нестабильном интернете. (кэш хранится в папке
|
||||||
|
/tmp/ymd)
|
||||||
|
|
||||||
ID:
|
ID:
|
||||||
--artist-id <ID исполнителя>
|
--artist-id <ID исполнителя>
|
||||||
|
|
|
||||||
52
main.py
52
main.py
|
|
@ -5,6 +5,7 @@ import hashlib
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
@ -15,6 +16,7 @@ from typing import Optional
|
||||||
import eyed3
|
import eyed3
|
||||||
from eyed3.id3.frames import ImageFrame
|
from eyed3.id3.frames import ImageFrame
|
||||||
from requests import Session
|
from requests import Session
|
||||||
|
from requests_cache import CachedSession, FileCache
|
||||||
|
|
||||||
MD5_SALT = 'XGRlBW9FXlekgbPrRHuSiA'
|
MD5_SALT = 'XGRlBW9FXlekgbPrRHuSiA'
|
||||||
ENCODED_BY = 'https://github.com/llistochek/yandex-music-downloader'
|
ENCODED_BY = 'https://github.com/llistochek/yandex-music-downloader'
|
||||||
|
|
@ -24,6 +26,9 @@ DEFAULT_PATH_PATTERN = Path('#album-artist', '#album', '#number - #title')
|
||||||
DEFAULT_COVER_RESOLUTION = 400
|
DEFAULT_COVER_RESOLUTION = 400
|
||||||
DEFAULT_LOG_LEVEL = 'INFO'
|
DEFAULT_LOG_LEVEL = 'INFO'
|
||||||
|
|
||||||
|
CACHE_EXPIRE_AFTER = dt.timedelta(hours=8)
|
||||||
|
CACHE_DIR = Path(tempfile.gettempdir()) / 'ymd'
|
||||||
|
|
||||||
TRACK_RE = re.compile(r'track/(\d+)$')
|
TRACK_RE = re.compile(r'track/(\d+)$')
|
||||||
ALBUM_RE = re.compile(r'album/(\d+)$')
|
ALBUM_RE = re.compile(r'album/(\d+)$')
|
||||||
ARTIST_RE = re.compile(r'artist/(\d+)$')
|
ARTIST_RE = re.compile(r'artist/(\d+)$')
|
||||||
|
|
@ -335,10 +340,6 @@ if __name__ == '__main__':
|
||||||
common_group.add_argument('--embed-cover',
|
common_group.add_argument('--embed-cover',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Встраивать обложку в .mp3 файл')
|
help='Встраивать обложку в .mp3 файл')
|
||||||
common_group.add_argument(
|
|
||||||
'--stick-to-artist',
|
|
||||||
action='store_true',
|
|
||||||
help='Загружать только альбомы созданные данным исполнителем')
|
|
||||||
common_group.add_argument('--cover-resolution',
|
common_group.add_argument('--cover-resolution',
|
||||||
default=DEFAULT_COVER_RESOLUTION,
|
default=DEFAULT_COVER_RESOLUTION,
|
||||||
metavar='<Разрешение обложки>',
|
metavar='<Разрешение обложки>',
|
||||||
|
|
@ -350,12 +351,22 @@ if __name__ == '__main__':
|
||||||
metavar='<Задержка>',
|
metavar='<Задержка>',
|
||||||
type=int,
|
type=int,
|
||||||
help=help_str('Задержка между запросами, в секундах'))
|
help=help_str('Задержка между запросами, в секундах'))
|
||||||
|
common_group.add_argument('--stick-to-artist',
|
||||||
|
action='store_true',
|
||||||
|
help='Загружать альбомы, созданные'
|
||||||
|
' только данным исполнителем')
|
||||||
common_group.add_argument('--only-music',
|
common_group.add_argument('--only-music',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Загружать только музыкальные альбомы')
|
help='Загружать только музыкальные альбомы'
|
||||||
|
' (пропускать подкасты и аудиокниги)')
|
||||||
|
common_group.add_argument('--enable-caching',
|
||||||
|
action='store_true',
|
||||||
|
help='Включить кэширование. Данная опция полезна'
|
||||||
|
' при нестабильном интернете.'
|
||||||
|
f' (кэш хранится в папке {CACHE_DIR})')
|
||||||
common_group.add_argument('--debug',
|
common_group.add_argument('--debug',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Включить отладочный вывод')
|
help=argparse.SUPPRESS)
|
||||||
|
|
||||||
def args_playlist_id(arg: str) -> PlaylistId:
|
def args_playlist_id(arg: str) -> PlaylistId:
|
||||||
arr = arg.split('/')
|
arr = arg.split('/')
|
||||||
|
|
@ -406,20 +417,33 @@ if __name__ == '__main__':
|
||||||
datefmt='%H:%M:%S',
|
datefmt='%H:%M:%S',
|
||||||
level=logging.DEBUG if args.debug else logging.ERROR)
|
level=logging.DEBUG if args.debug else logging.ERROR)
|
||||||
|
|
||||||
def response_hook(resp, **_kwargs):
|
session = Session()
|
||||||
|
cached_session = Session()
|
||||||
|
if args.enable_caching:
|
||||||
|
cached_session = CachedSession(backend=FileCache(cache_name=CACHE_DIR),
|
||||||
|
expire_after=CACHE_EXPIRE_AFTER)
|
||||||
|
|
||||||
|
def setup_session(session: Session):
|
||||||
|
|
||||||
|
def response_hook(resp, **kwargs):
|
||||||
|
del kwargs
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
target_headers = ['application/json', 'text/xml']
|
target_headers = ['application/json', 'text/xml']
|
||||||
if any(h in resp.headers['Content-Type'] for h in target_headers):
|
if any(h in resp.headers['Content-Type']
|
||||||
|
for h in target_headers):
|
||||||
logger.debug(resp.text)
|
logger.debug(resp.text)
|
||||||
|
if not getattr(resp, 'from_cache', False):
|
||||||
time.sleep(args.delay)
|
time.sleep(args.delay)
|
||||||
|
|
||||||
session = Session()
|
|
||||||
session.hooks = {'response': response_hook}
|
session.hooks = {'response': response_hook}
|
||||||
session.cookies.set('Session_id', args.session_id, domain='yandex.ru')
|
session.cookies.set('Session_id', args.session_id, domain='yandex.ru')
|
||||||
session.headers['User-Agent'] = args.user_agent
|
session.headers['User-Agent'] = args.user_agent
|
||||||
session.headers['X-Retpath-Y'] = urllib.parse.quote_plus(
|
session.headers['X-Retpath-Y'] = urllib.parse.quote_plus(
|
||||||
'https://music.yandex.ru')
|
'https://music.yandex.ru')
|
||||||
|
|
||||||
|
setup_session(session)
|
||||||
|
setup_session(cached_session)
|
||||||
|
|
||||||
result_tracks: list[BasicTrackInfo] = []
|
result_tracks: list[BasicTrackInfo] = []
|
||||||
|
|
||||||
if args.url is not None:
|
if args.url is not None:
|
||||||
|
|
@ -437,7 +461,7 @@ if __name__ == '__main__':
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if args.artist_id is not None:
|
if args.artist_id is not None:
|
||||||
artist_info = get_artist_info(session, args.artist_id)
|
artist_info = get_artist_info(cached_session, args.artist_id)
|
||||||
albums_count = 0
|
albums_count = 0
|
||||||
for album in artist_info.albums:
|
for album in artist_info.albums:
|
||||||
if args.stick_to_artist and album.artists[0] != artist_info.name:
|
if args.stick_to_artist and album.artists[0] != artist_info.name:
|
||||||
|
|
@ -448,19 +472,19 @@ if __name__ == '__main__':
|
||||||
print(f'Альбом "{album.title}" пропущен'
|
print(f'Альбом "{album.title}" пропущен'
|
||||||
' т.к. не является музыкальным')
|
' т.к. не является музыкальным')
|
||||||
continue
|
continue
|
||||||
full_album = get_full_album_info(session, album.id)
|
full_album = get_full_album_info(cached_session, album.id)
|
||||||
result_tracks.extend(full_album.tracks)
|
result_tracks.extend(full_album.tracks)
|
||||||
albums_count += 1
|
albums_count += 1
|
||||||
print(artist_info.name)
|
print(artist_info.name)
|
||||||
print(f'Альбомов: {albums_count}')
|
print(f'Альбомов: {albums_count}')
|
||||||
elif args.album_id is not None:
|
elif args.album_id is not None:
|
||||||
album = get_full_album_info(session, args.album_id)
|
album = get_full_album_info(cached_session, args.album_id)
|
||||||
print(album.title)
|
print(album.title)
|
||||||
result_tracks = album.tracks
|
result_tracks = album.tracks
|
||||||
elif args.track_id is not None:
|
elif args.track_id is not None:
|
||||||
result_tracks = [get_full_track_info(session, args.track_id)]
|
result_tracks = [get_full_track_info(cached_session, args.track_id)]
|
||||||
elif args.playlist_id is not None:
|
elif args.playlist_id is not None:
|
||||||
result_tracks = get_playlist(session, args.playlist_id)
|
result_tracks = get_playlist(cached_session, args.playlist_id)
|
||||||
|
|
||||||
print(f'Треков: {len(result_tracks)}')
|
print(f'Треков: {len(result_tracks)}')
|
||||||
covers: dict[str, bytes] = {}
|
covers: dict[str, bytes] = {}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
requests
|
requests
|
||||||
|
requests-cache
|
||||||
eyed3
|
eyed3
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue