Качаем музыку гигами
Вспомнил, что в начале 2000-х качал музыку с http://music.lib.ru. Сайт всегда радовал редкими и интересными композициями. Недавно совершенно случайно вспомнил о сайте, зашел, и о чудо! Он до сих пор работает и с тех пор ничуть не изменился! Ко мне пришла мысль, почему бы не скачать немного музыки и послушать. Чтобы не качать песни по одной, я решил автоматизировать эту задачу и заодно написать для вас этот туториал.
Нам понадобятся библиотеки.
- requests для HTTP запросов, включая скачивание файлов
- BeautifulSoup (bs4) для парсинга HTML на предмет ссылок на музыку.
pip install requests bs4
- multiprocessing — для распараллеливания загрузок
- urllib.parse — для парcинга URL (достать имя файла)
- functools — для декоратора retry
- time — чтобы поспать
- os — для работы с путями ОС
import requests from urllib.parse import urlparse from bs4 import BeautifulSoup from functools import wraps import time import os
Я люблю фолк, поэтому в примере качать будем его. Вы, естественно, можете выбрать любой жанр или исполнителя на ваш вкус. Нужно просто сделать генератор, который будет выдавать URL страниц, где будут искаться ссылки на музыку.
# страницы 1 по 15 def page_generator(): for i in range(1, 16): yield f'http://music.lib.ru/janr/index_janr_23-.shtml'
list(page_generator()) Out[5]: ['http://music.lib.ru/janr/index_janr_23-1.shtml', 'http://music.lib.ru/janr/index_janr_23-2.shtml', 'http://music.lib.ru/janr/index_janr_23-3.shtml', 'http://music.lib.ru/janr/index_janr_23-4.shtml', 'http://music.lib.ru/janr/index_janr_23-5.shtml', 'http://music.lib.ru/janr/index_janr_23-6.shtml', 'http://music.lib.ru/janr/index_janr_23-7.shtml', 'http://music.lib.ru/janr/index_janr_23-8.shtml', 'http://music.lib.ru/janr/index_janr_23-9.shtml', 'http://music.lib.ru/janr/index_janr_23-10.shtml', 'http://music.lib.ru/janr/index_janr_23-11.shtml', 'http://music.lib.ru/janr/index_janr_23-12.shtml', 'http://music.lib.ru/janr/index_janr_23-13.shtml', 'http://music.lib.ru/janr/index_janr_23-14.shtml', 'http://music.lib.ru/janr/index_janr_23-15.shtml']
Куда будем качать:
DOWNLOAD_TO = os.path.expanduser('~/Downloads/music_lib_ru_test')
При скачивании могут быть ошибки, поэтому этот декоратор будет полезен. Если декорируемая функция бросила исключение, что он совершит еще попытки через несколько секунд:
# декоратор, который делает несколько попыток выполнить функцию def retry(tries=4, delay=3): def deco_retry(f): @wraps(f) def f_retry(*args, **kwargs): for _ in range(tries): try: return f(*args, **kwargs) except: time.sleep(delay) return f(*args, **kwargs) return f_retry return deco_retry
Эта функция определяет, является ли URL ссылкой на музыку (по расширению):
def is_music(href: str): href = href.lower() for ext in ['.mp3', '.wma', '.ogg']: if href.endswith(ext): return True return False
BeautifulSoup помогает нам парсить HTML страниц каталога.
def all_links(html): # создаем парсер soup = BeautifulSoup(html, 'html.parser') # находим все тэги all_a = soup.find_all('a') # у каждого тэга получаем атрибут href (адрес ссылки) и выплевываем их из генератора yield from map(lambda el: el.get('href'), all_a)
Эта функция качает одну страницу из каталога, парсит, достает все ссылки ( all_links ), фильтрует из них музыкальные ( is_music ):
@retry(5) def do_page(page_url): print(f'Downloading list: ') html = requests.get(page_url).text links = all_links(html) music_links = filter(is_music, links) return list(music_links)
Также нужна функция flatten , чтобы из списка списков ссылок составить общий одно-уровневый список.
def flatten(l): return [item for sublist in l for item in sublist]
Скачаем каталог ссылок:
from multiprocessing import Pool # пул из 4-х процессов для параллельного скачивания pool = Pool(4) # к каждой URL из page_generator мы применим ф-цию do_page mp3_urls = pool.map(do_page, page_generator()) # расплющим список mp3_urls = flatten(mp3_urls) # выведем немного: print(mp3_urls[:10]) total = len(mp3_urls) print('total:', total)
Downloading list: http://music.lib.ru/janr/index_janr_23-2.shtml Downloading list: http://music.lib.ru/janr/index_janr_23-3.shtml Downloading list: http://music.lib.ru/janr/index_janr_23-1.shtml Downloading list: http://music.lib.ru/janr/index_janr_23-4.shtml . ['http://mp3.music.lib.ru/mp3/s/shergin_b_w/shergin_b_w-diwnyj_gudochek-1.mp3', 'http://mp3.music.lib.ru/mp3/s/shergin_b_w/shergin_b_w-diwnyj_gudochek-2.mp3', 'http://mp3.music.lib.ru/mp3/k/kalinin_a/kalinin_a-. ] total: 3704
Каждую песню нужно теперь скачать. Для одной скачивания одной песни напишем функцию:
@retry(5) def download_music_piece(url, i, total, download_to): """ url - ссылка i - номер песни (для отображения прогресса) total - всего песен download_to - каталог, куда сохранить """ print(f'[ / ] ') # парсим URL, чтобы достать оригинальное имя файла original_path = urlparse(url).path original_path = original_path[1:] # убираем передний слэш / (это важно!) # чисто имя файла filename = os.path.basename(original_path) # будущий локальный каталог файла dirname = os.path.join(download_to, os.path.dirname(original_path)) # полное локальное имя файла full_local_path = os.path.join(dirname, filename) # проверка, не скачали ли мы уже этот файл ранее (если да, пропускаем) if not os.path.isfile(full_local_path): # создадим каталог для него, если еще нет os.makedirs(dirname, exist_ok=True) # открываем локлаьный файл для записи бинарно with open(full_local_path, 'wb') as f: # делаем запрос на скачивание r = requests.get(url) if r.status_code == 200: # если ответ ОК (200), то все кусочки пишем в файл for c in r: f.write(c)
Теперь для каждого файла мы его скачаем также в мульти-процессном пуле для ускорения. Но для начала мы снабдим каждую запись в mp3_urls номером песни, общим числом песен и каталогом для скачивания, потому что download_music_piece принимает как раз эти 4 аргумента, а не лишь одну ссылку.
mp3_urls = [(url, i, total, DOWNLOAD_TO) for i, url in enumerate(mp3_urls, start=1)] mp3_urls[:5]
[('http://mp3.music.lib.ru/mp3/s/shergin_b_w/shergin_b_w-diwnyj_gudochek-1.mp3', 1, 3704, '/Users/tirinox/Downloads/music_lib_ru_test'), ('http://mp3.music.lib.ru/mp3/s/shergin_b_w/shergin_b_w-diwnyj_gudochek-2.mp3', 2, 3704, '/Users/tirinox/Downloads/music_lib_ru_test'), ('http://mp3.music.lib.ru/mp3/k/kalinin_a/kalinin_a-matushke_moej-2.mp3', 3, 3704, '/Users/tirinox/Downloads/music_lib_ru_test'), ('http://mp3.music.lib.ru/mp3/p/papisowa_a/papisowa_a-planxty_capitan_okane-2.mp3', 4, 3704, '/Users/tirinox/Downloads/music_lib_ru_test'), ('http://mp3.music.lib.ru/mp3/a/anonymous/anonymous-radio_radonezh-2.mp3', 5, 3704, '/Users/tirinox/Downloads/music_lib_ru_test')]
pool.starmap — передаст содержимое кортежа в аргументы ф-ции download_music_piece(url, i, total, download_to) :
# после запуска - файлы начнут качаться: pool.starmap(download_music_piece, mp3_urls)
Музыка начала качаться, нужно немного подождать.
Полный код ноутбука здесь. Думаю, вы легко сможете адаптировать скрипт к скачиванию любых других материалов с разных сайтов.
P.S. Спасибо авторам и редакторам сайта, и, конечно же, певцам и музыкантам.
Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway
Песни
Чтобы использовать музыку в игре нужно нажать на кнопку «Import» в интерфейсе музыкального инструмента. Если вы хотите больше информации о синтезаторе, музыке с другой библиотекой, или музыке, что хорошо звучит на определённых инструментах, загляните на страницу продвинутых песен.
- 1 Музыкальные инструменты
- 2 Как создавать свою музыку
- 3 Как добавить музыку на вики
- 4 Жанры
- 5 См. также
Музыкальные инструменты
Некоторые инструменты можно создать, другие вы можете заказать в карго, или найти в комнатах, например в баре. Каждый инструмент отличается звуком и некоторыми настройками, но все они используются для проигрывания музыки, с помощью шаблонов, созданных игроками.
Инструменты: Все доступные музыкальные инструменты.
Instrument | Description |
Space Minimoog | Аналог синтезатора. Расположен в Баре. |
---|---|
Grand Piano | Космическое пианино. Выглядит и звучит как обычное, но может работать даже без музыканта. |
Synthesizer | Цифровое пианино, которое может генерировать много различных звуков. |
Violin | Деревянный музыкальный инструмент, имеющий 4 струны и смычок. «Дьявол спустился с космоса, он искал ассистента для грифа.» |
Banjo | Банджо марки «Мура». Грубо говоря, это просто барабан с грифом и струнами. |
Guitar | Сделана из дерева и имеет бронзовые струны. |
Electric Guitar | Удовлетворяет вашу потребность в тяжёлой музыке. |
Glockenspiel | Гладкие металлические клавиши идеально подходят для марширующего оркестра. |
Accordion | Пун-пун в сделку не входил. |
Trumpet | Для оповещения о прибытии короля! |
Saxophone | Этот успокаивающий звук обязательно вызовет слезы у вашей аудитории. |
Trombone | Духовой амбушюрный музыкальный инструмент. |
Recorder | Если вы знаете, что это — вы умеете на этом играть. |
Harmonica | На случай, если на вас грянет космическая хандра. Можно найти в пермабриге. |
Xylophone | Ударный инструмент со звонким звуком. |
Gilded bike horn | Изысканно украшенный велосипедный гудок, способный гудеть на самых разных нотах. Чаще всего используется клоуном. |
Как создавать свою музыку
Вы можете создать музыку из любого midi файла. Вам потребуется midi2piano и python 3.
midi2piano: скачивается здесь — или на GitHub
Python 3: скачивается здесь
- Установите python 3.
- Распакуйте midi2piano в любую папку. (Если вы скачивали с гитхаба, то убедитесь, что у вас загружены все файлы и папки)
- Запустите midi2piano.py (файл запустится автоматически с помощью python). После этого должно открыться окно с выбором midi файла.
- После того, как вы укажете путь к midi файлу, программа скопирует готовый шаблон в буфер обмена. Его можно будет использовать сразу в игре, или же скопировать в блокнот.
Заметка 1: Множество известных песен можно найти в интернете в формате midi.
Заметка 2: Вам может потребоваться отредактировать midi файл, чтобы убрать лишние дорожки или ноты (например с помощью любого бесплатного онлайн секвенсора — просто удалите лишнее и конвертируйте обратно в midi файл).
Заметка 3: Внутриигровые инструменты не очень хорошо работают с аккордами — звучание будет лучше, если ноты будут идти друг за другом последовательно, а сам файл midi не будет излишне перегружен количеством дорожек. Одна часто повторяющаяся нота может ломать плавность звучания — вы можете попробовать объединить несколько повторяющихся нот в одну длинную.
Заметка 4: Вы можете отредактировать файл midi2piano.py чтобы точно настроить некоторые параметры. Прочитайте readme.txt чтобы узнать больше.
Как добавить музыку на вики
Шаблон, который нужно использовать, через режим «редактирования кода»:
>> |notes=>> >>
Когда вы добавите песню: Вы должны убедится, что правильно выбрали жанр (под каждый создана отдельная страница).
Жанры
Вся музыка разбита по данным страницам:
См. также
Аналогичные страница на аналогичных вики-проектах:
Ниже перевод
Я хочу ставить проигрываемую в фоне музыку на паузу и/или продолжать воспроизведение используя питон, нашёл такой вариант, который использует pynput :
from pynput.keyboard import Controller, Key c = Controller() c.press(Key.media_play_pause)
Но аудио всё равно продолжает проигрываться. Похоже ошибок нет, но оно не работает.
Ответ
Возможно тебе стоит попробовать playerctl, утилита для командной строки, которую можно использовать через:
subprocess.call(("playerctl", "play-pause"))
Однако, playerctl возможно не установлена в твоей системе, то надо сделать сдедующее:
- sudo apt install playerctl ,
- pacman -Syu playerctl ,
- sudo dnf install playerctl or
- sudo zypper install playerctl
(в зависимости от дистрибутива)
Таким образом нет необходимости в pynput , вместо него subprocess ( import subprocess ). Если тебе не важны стиль и безопасность, ты можешь, конечно же, использовать os.system(«playerctl play-pause»)
Как добавить жанр музыки в на python
МЕРОПРИЯТИЯ
Хакатон GO.ALGO
01 декабря Москва Онлайн Бесплатно
Комментарии
Популярные По порядку
Не удалось загрузить комментарии.
ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ
ООП на Python: концепции, принципы и примеры реализации
Программирование на Python допускает различные методологии, но в его основе лежит объектный подход, поэтому работать в стиле ООП на Python очень просто.
Пишем свою нейросеть: пошаговое руководство
Отличный гайд про нейросеть от теории к практике. Вы узнаете из каких элементов состоит ИНС, как она работает и как ее создать самому.
Программирование на Python: от новичка до профессионала
Пошаговая инструкция для всех, кто хочет изучить программирование на Python (или программирование вообще), но не знает, куда сделать первый шаг.