трансфер с гитхаба
This commit is contained in:
+117
@@ -0,0 +1,117 @@
|
||||
import requests
|
||||
import os
|
||||
from yandex_music import Client
|
||||
|
||||
def get_itunes_search_data(query):
|
||||
url = "https://itunes.apple.com/search"
|
||||
params = {"term": query, "entity": "album", "limit": 1}
|
||||
try:
|
||||
response = requests.get(url, params=params)
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"iTunes API Error: {e}")
|
||||
return None
|
||||
|
||||
def extract_itunes_album(data):
|
||||
if not data or data.get("resultCount") == 0:
|
||||
return None
|
||||
return data["results"][0]
|
||||
|
||||
def get_itunes_tracks(album_id):
|
||||
params = {"id": album_id, "entity": "song"}
|
||||
response = requests.get("https://itunes.apple.com/lookup", params=params)
|
||||
results = response.json().get("results", [])
|
||||
return results[1:] if len(results) > 1 else []
|
||||
|
||||
def format_itunes_track(item, artist_name):
|
||||
ms = item.get('trackTimeMillis', 0)
|
||||
duration = f"{ms // 60000}:{(ms // 1000) % 60:02d}"
|
||||
return {
|
||||
"no": item.get("trackNumber"),
|
||||
"artist": artist_name,
|
||||
"title": item.get("trackName"),
|
||||
"duration": duration
|
||||
}
|
||||
|
||||
|
||||
def get_yandex_client():
|
||||
try:
|
||||
return Client().init()
|
||||
except:
|
||||
return None
|
||||
|
||||
def find_yandex_album(client, query):
|
||||
search = client.search(query, type_='album')
|
||||
if not search.albums or not search.albums.results:
|
||||
return None
|
||||
return search.albums.results[0]
|
||||
|
||||
def format_yandex_track(track):
|
||||
sec = track.duration_ms // 1000
|
||||
duration = f"{sec // 60}:{sec % 60:02d}"
|
||||
artists = ", ".join([a.name for a in track.artists])
|
||||
return {
|
||||
"no": getattr(track, 'number', 0),
|
||||
"artist": artists,
|
||||
"title": track.title,
|
||||
"duration": duration
|
||||
}
|
||||
|
||||
|
||||
def process_itunes(query):
|
||||
data = get_itunes_search_data(query)
|
||||
album = extract_itunes_album(data)
|
||||
if not album:
|
||||
return None
|
||||
|
||||
raw_tracks = get_itunes_tracks(album["collectionId"])
|
||||
artist = album.get("artistName", "Unknown")
|
||||
|
||||
return {
|
||||
"title": album["collectionName"],
|
||||
"year": album["releaseDate"][:4],
|
||||
"tracks": [format_itunes_track(t, artist) for t in raw_tracks]
|
||||
}
|
||||
|
||||
def process_yandex(query):
|
||||
client = get_yandex_client()
|
||||
if not client: return None
|
||||
|
||||
album_info = find_yandex_album(client, query)
|
||||
if not album_info: return None
|
||||
|
||||
full_album = client.albums_with_tracks(album_info.id)
|
||||
tracks = []
|
||||
for vol in full_album.volumes:
|
||||
for t in vol:
|
||||
tracks.append(format_yandex_track(t))
|
||||
|
||||
return {
|
||||
"title": album_info.title,
|
||||
"year": album_info.year or "Unknown",
|
||||
"tracks": tracks
|
||||
}
|
||||
|
||||
def save_to_file(album_data):
|
||||
filename = f"{album_data['title']}.txt"
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
for t in album_data['tracks']:
|
||||
line = f"{t['no']}. {t['artist']} - {t['title']} ({t['duration']})"
|
||||
print(line)
|
||||
f.write(f"{t['artist']} {t['title']}\n")
|
||||
print(f"\nГотово! Сохранено в {filename}")
|
||||
|
||||
|
||||
def main(request):
|
||||
print(f"Поиск '{request}' в iTunes...")
|
||||
result = process_itunes(request)
|
||||
|
||||
if not result:
|
||||
print("В iTunes не найдено. Ищем в Яндекс.Музыке...")
|
||||
result = process_yandex(request)
|
||||
|
||||
if result:
|
||||
print(f"Найдено: {result['title']} ({result['year']})")
|
||||
save_to_file(result)
|
||||
else:
|
||||
print(f"Альбом '{request}' не найден ни в одном источнике.")
|
||||
@@ -0,0 +1,75 @@
|
||||
import io
|
||||
import requests
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
from yandex_music import Client
|
||||
from PIL import Image
|
||||
from mutagen.mp3 import MP3
|
||||
from mutagen.id3 import ID3, APIC
|
||||
|
||||
def get_yandex_cover(query, settings):
|
||||
try:
|
||||
client = Client().init()
|
||||
time.sleep(settings["delay"])
|
||||
search_result = client.search(query, type_='track')
|
||||
if search_result.tracks and search_result.tracks.results:
|
||||
track_obj = search_result.tracks.results[0]
|
||||
if track_obj.og_image:
|
||||
return "https://" + track_obj.og_image.replace('%%', '1000x1000')
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
def get_itunes_cover(query, settings):
|
||||
url = "https://itunes.apple.com/search"
|
||||
params = {"term": query, "entity": "song", "limit": 1}
|
||||
try:
|
||||
time.sleep(settings["delay"])
|
||||
response = requests.get(url, params=params, timeout=5)
|
||||
data = response.json()
|
||||
if data.get("resultCount", 0) > 0:
|
||||
return data["results"][0]["artworkUrl100"].replace("100x100bb.jpg", "1000x1000bb.jpg")
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
def get_best_cover(query, settings):
|
||||
cover_url = get_itunes_cover(query, settings)
|
||||
if not cover_url:
|
||||
cover_url = get_yandex_cover(query, settings)
|
||||
return cover_url
|
||||
|
||||
def set_cover(track_path, request):
|
||||
with open("settings.json", "r", encoding="utf-8") as file:
|
||||
settings = json.load(file)
|
||||
cover_url = get_best_cover(request, settings)
|
||||
if not cover_url:
|
||||
return
|
||||
|
||||
try:
|
||||
response = requests.get(cover_url, timeout=10)
|
||||
img = Image.open(io.BytesIO(response.content)).convert("RGB")
|
||||
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="JPEG", quality=90)
|
||||
img_data = buffer.getvalue()
|
||||
|
||||
audio = MP3(track_path, ID3=ID3)
|
||||
if audio.tags is None:
|
||||
audio.add_tags()
|
||||
|
||||
audio.tags.add(
|
||||
APIC(
|
||||
encoding=3,
|
||||
mime='image/jpeg',
|
||||
type=3,
|
||||
desc='Cover',
|
||||
data=img_data
|
||||
)
|
||||
)
|
||||
audio.save()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Ошибка: {e}")
|
||||
return False
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
import requests
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
from bs4 import BeautifulSoup
|
||||
from tqdm import tqdm
|
||||
|
||||
def ping():
|
||||
pages = ["https://rus.hitmotop.com/", "https://eu.hitmo-top.com/"]
|
||||
for page in pages:
|
||||
status = requests.get(page)
|
||||
if status.status_code == 200:
|
||||
return page
|
||||
print("Ресурсы не доступны")
|
||||
sys.exit()
|
||||
|
||||
def parse(request, page, settings):
|
||||
url = page + "search?q=" + request.replace(" ", "%20")
|
||||
time.sleep(settings["delay"])
|
||||
content = BeautifulSoup(requests.get(url).text, "html.parser")
|
||||
return content
|
||||
|
||||
def get_artists(content):
|
||||
return [artists.get_text(strip=True) for artists in content.find_all("div", class_="track__desc")]
|
||||
|
||||
def get_titles(content):
|
||||
return [titles.get_text(strip=True) for titles in content.find_all("div", class_="track__title")]
|
||||
|
||||
def get_links(content):
|
||||
return [links.get("href") for links in content.find_all("a", class_="track__download-btn")]
|
||||
|
||||
def get_data_dict(content):
|
||||
dictionary = {
|
||||
i: [artist, title, link]
|
||||
for i, (artist, title, link) in enumerate(zip(get_artists(content), get_titles(content), get_links(content)))
|
||||
}
|
||||
return dictionary
|
||||
|
||||
def get_url(index, dictionary):
|
||||
return dictionary[index][2]
|
||||
|
||||
def handle():
|
||||
selected_index = int(input("Скачать трек: "))
|
||||
return selected_index
|
||||
|
||||
def playlist():
|
||||
return 0
|
||||
|
||||
def get_filename(index, dictionary):
|
||||
filename = f"{dictionary[index][0]} - {dictionary[index][1]}.mp3"
|
||||
filename = re.sub(r'[*"?<>|:$&()\[\]!/]+', "", filename)
|
||||
return filename
|
||||
|
||||
def get_path_to_file(filename, settings):
|
||||
os.makedirs(settings["save to"], exist_ok=True)
|
||||
path_to_file = os.path.join(settings["save to"], filename)
|
||||
return path_to_file
|
||||
|
||||
def print_content(dictionary):
|
||||
for i in range(len(dictionary)):
|
||||
print(f"{i}. {dictionary[i][0]} - {dictionary[i][1]}")
|
||||
return None
|
||||
|
||||
def download(url, path_to_file, filename, settings):
|
||||
time.sleep(settings["delay"])
|
||||
with requests.get(url, stream=True, headers={"User-Agent": "Mozilla/5.0"}) as r:
|
||||
r.raise_for_status()
|
||||
size = int(r.headers.get('content-length', 0))
|
||||
|
||||
with open(path_to_file, 'wb') as f, tqdm(total=size, unit='B', unit_scale=True) as pbar:
|
||||
for chunk in r.iter_content(8192):
|
||||
pbar.update(f.write(chunk))
|
||||
print(f"Скачано: {filename}")
|
||||
|
||||
def main(request, mode):
|
||||
try:
|
||||
with open("settings.json", "r", encoding="utf-8") as file:
|
||||
settings = json.load(file)
|
||||
except Exception as e:
|
||||
print(f"Ошибка открытия файла: {e}")
|
||||
sys.exit()
|
||||
page = ping()
|
||||
content = parse(request, page, settings)
|
||||
dictionary = get_data_dict(content)
|
||||
if not dictionary:
|
||||
print(f"По запросу {request} ничего не найдено.")
|
||||
return
|
||||
if mode == "handle":
|
||||
print_content(dictionary)
|
||||
index = handle()
|
||||
else:
|
||||
index = playlist()
|
||||
url = get_url(index, dictionary)
|
||||
filename = get_filename(index, dictionary)
|
||||
path_to_file = get_path_to_file(filename, settings)
|
||||
download(url, path_to_file, filename, settings)
|
||||
|
||||
return path_to_file
|
||||
@@ -0,0 +1,71 @@
|
||||
import json
|
||||
import sys
|
||||
import re
|
||||
import random
|
||||
from yandex_music import Client
|
||||
|
||||
def yandex(html_):
|
||||
pattern = r"playlist/([\w\.-]+)/(\d+)"
|
||||
|
||||
match = re.search(pattern, html_)
|
||||
|
||||
if match:
|
||||
owner = match.group(1)
|
||||
kind = match.group(2)
|
||||
else:
|
||||
sys.exit()
|
||||
|
||||
client = Client().init()
|
||||
|
||||
try:
|
||||
playlist = client.users_playlists(kind, owner)
|
||||
|
||||
print(f"\nПлейлист: {playlist.title}")
|
||||
print(f"Всего треков: {playlist.track_count}")
|
||||
print("-" * 30)
|
||||
|
||||
file = open(f"{playlist.title}.txt", "w", encoding="utf-8")
|
||||
|
||||
for item in playlist.tracks:
|
||||
track = item.track
|
||||
artists = ", ".join([a.name for a in track.artists])
|
||||
title = track.title
|
||||
file.write(f"{artists} {title}\n")
|
||||
print(f"{artists} — {title}")
|
||||
|
||||
print(f"\n{playlist.title}.txt плейлист сформирован")
|
||||
file.close()
|
||||
|
||||
sys.exit()
|
||||
|
||||
except Exception:
|
||||
print(f"Ошибка при чтении плейлиста: {Exception}")
|
||||
sys.exit()
|
||||
|
||||
def spotify(playlist):
|
||||
try:
|
||||
with open(playlist, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Ошибка открытия файла: {e}")
|
||||
sys.exit()
|
||||
|
||||
temp_name = str(random.randint(0, 2**32 -1))[:5]
|
||||
|
||||
items = data["data"]["playlistV2"]["content"]["items"]
|
||||
|
||||
file = open(f"{temp_name}.txt", "w", encoding="utf-8")
|
||||
|
||||
for item in items:
|
||||
track = item["itemV2"]["data"]
|
||||
|
||||
title = track["name"]
|
||||
artist = track["artists"]["items"][0]["profile"]["name"]
|
||||
file.write(f"{artist} {title}\n")
|
||||
print(f"{artist} — {title}")
|
||||
|
||||
|
||||
file.close()
|
||||
print(f"\n{temp_name}.txt плейлист сформирован")
|
||||
|
||||
sys.exit()
|
||||
@@ -0,0 +1,53 @@
|
||||
import yt_dlp
|
||||
import os
|
||||
import json
|
||||
|
||||
def download_track(input_):
|
||||
with open ("settings.json", "r", encoding="utf-8") as data:
|
||||
settings = json.load(data)
|
||||
|
||||
query = f"ytsearch1:{input_}"
|
||||
|
||||
if not os.path.exists(settings["save to"]):
|
||||
os.makedirs(settings["save to"])
|
||||
|
||||
ydl_opts = {
|
||||
"format": "bestaudio/best",
|
||||
"postprocessors": [{
|
||||
"key": "FFmpegExtractAudio",
|
||||
"preferredcodec": "mp3",
|
||||
"preferredquality": "320",
|
||||
}],
|
||||
|
||||
"proxy": settings["proxy"],
|
||||
|
||||
"extractor_args": {
|
||||
"youtube": {
|
||||
"player_client": ["android"],
|
||||
"skip": ["webpage"],
|
||||
}
|
||||
},
|
||||
|
||||
"nocheckcertificate": True,
|
||||
"outtmpl": settings["save to"] + "%(title)s.%(ext)s",
|
||||
"quiet": False,
|
||||
}
|
||||
|
||||
try:
|
||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||
info_dict = ydl.extract_info(query, download=True)
|
||||
|
||||
if 'entries' in info_dict:
|
||||
video_info = info_dict['entries'][0]
|
||||
else:
|
||||
video_info = info_dict
|
||||
|
||||
file_path = ydl.prepare_filename(video_info)
|
||||
final_path = os.path.splitext(file_path)[0] + ".mp3"
|
||||
|
||||
print(f"Скачано: {final_path}")
|
||||
return final_path
|
||||
|
||||
except Exception as e:
|
||||
print(f"Ошибка при скачивании: {e}")
|
||||
return False
|
||||
Reference in New Issue
Block a user