Récupérer une liste de lecture Apple
-
Je suis récemment allé à une soirée où le choix musical m’a plu. La personne qui mettait sa musique a découvert qu’elle pouvait me partager sa liste en m’envoyant un lien qui pointe vers
https://music.apple.com/fr/playlist/[quelque chose]
.Je n’ai pas iTunes. Mon but : récupérer cette liste et en faire un truc que je peux utiliser. Ce journal est aussi un prétexte pour jouer avec jq, un outil pour faire des requêtes sur des données formatées en JSON.
Prenons une liste trouvée au hasard sur internet et travaillons dessus en mode bidouille rapide et sale : https://music.apple.com/us/playlist/playlist-by-me/pl.ae7cd2db31fc4d519725b6747b9074a5
Nous avons besoin de :
- Firefox et son ardoise Javascript
- un éditeur de texte
- un shell
jq
grep
curl
Allons visiter la liste avec Firefox. On est accueilli par un bandeau « Vous devez activer les DRM pour certaines des pistes audio ou vidéo de cette page ». On va pouvoir ignorer ce message, cliquer sur sa croix et continuer notre affaire.
La liste est affichée avec des éléments HTML simples. Avec les outils de développement, on repère vite que :
- chaque morceau est dans un élément avec la classe
tracklist-item__text
- dans les enfants de cet élément, on trouve le nom du morceau dans l’attribut
aria-label
d’un élément de classespread
- dans les enfants de cet élément, on trouve les artistes dans un attribut
data-test-song-artist-url
Sortons l’ardoise Javascript (Maj+F4). Dans cette ardoise, on peut lancer des codes en les sélectionnant et en faisant Ctrl+L.
Pour récupérer la liste des nœuds correspondant aux morceaux :
document.querySelectorAll(".tracklist-item__text")
Ou sa version supposément plus efficace :
document.getElementsByClassName("tracklist-item__text")
On va appliquer une fonction à chacun de ces éléments, pour récupérer le nom et l’artiste de chaque morceau.
Pour cela on va utiliser la fonctionmap
, qui appelle la fonction qu’on lui donne sur chaque élément et qui retourne un tableau contenant tous ces résultats.map
est une méthode des tableaux, il faut donc convertir le résultat des expressions précédentes en tableau.À l’ancienne :
[].slice.call(document.getElementsByClassName("tracklist-item__text"))
Avec la syntaxe de décomposition :
[... document.getElementsByClassName("tracklist-item__text")]
Sur ce tableau, on peut appeler
map
sur une fonction qui prend l’élément HTML correspondant au morceau, et qui le transforme en un objet contenant son titre et son artiste. On rajoute JSON.stringify pour récupérer le JSON :JSON.stringify([... document.getElementsByClassName("tracklist-item__text")]).map( track => ({ title: track.querySelector(".spread").getAttribute('aria-label'), artist: track.querySelector("[data-test-song-artist-url]").dataset.testSongArtistUrl }) ));
Avec Ctrl+L, on se retrouve avec un tableau du genre
[{'title': 'blah blah', 'artist': 'qqun'}, …]
.On enregistre ça dans un fichier
liste.json
. Et là, on peut faire certaines choses :Concaténer artiste et titre en vue de faire une recherche :
jq -r 'map(.artist + " " + .title)' liste.json
L’opérateur
map
applique une transformation à chaque élément. L’opération est ici une concaténation de l’artiste et du nom du morceau. On obtient le résultat au format JSON.Même chose, mais avec un résultat par ligne (sans JSON) :
jq -r 'map(.artist + " " + .title) | .[]' liste.json
Obtenir les adresses de recherche correspondantes sur YouTube :
jq -r 'map(.artist + " " + .title) | @uri "https://www.youtube.com/results?search_query=\(.[])"' liste.json
Dans une fonction qui lit le fichier json dans son entrée :
youtube_searches() { jq -r 'map(.artist + " " + .title) | @uri "https://www.youtube.com/results?search_query=\(.[])"' }
Étant donnée une liste d’adresse de recherche YouTube, récupérer l’adresse du premier résultat à coup de
curl $URL | grep -o '/watch?…'
. Attention, la fonction suivante n’est pas très polie, elle fait une requête vers YouTube par morceau. Vous pouvez vous faire kicker par YouTube. Aussi, j’ai rajouté un petitsleep 5
pour limiter les dégâts :youtube_first_results() { while read line; do printf "https://www.youtube.com%s\n" "$(curl -s "$line" | grep -o '/watch?v=[^"]\+' | head -1)" sleep 5 done }
Le script complet :
#!/usr/bin/env sh youtube_searches() { jq -r 'map(.artist + " " + .title) | @uri "https://www.youtube.com/results?search_query=\(.[])"' } youtube_first_results() { while read line; do printf "https://www.youtube.com%s\n" "$(curl -s "$line" | grep -o '/watch?v=[^"]\+' | head -1)" sleep 5 done } <"liste.json" youtube_searches | youtube_first_results >> liste-youtube.txt
Si vous souhaitez télécharger les morceaux plutôt qu’avoir leur liste, des outils font ça très bien et la fonction
youtube_first_results
est redondante avec des fonctionalités de téléchargement à partir d’une chaîne de recherche qui existent déjà.Bon dimanche, et bon vote pour celles et ceux qui voteront cet après midi !
Télécharger ce contenu au format Epub
Commentaires : voir le flux atom ouvrir dans le navigateur
https://linuxfr.org/users/raphj/journaux/recuperer-une-liste-de-lecture-apple
Sauf mention contraire, le site est placé sous double licence Creative Commons BY-SA et GNU Free Documentation License propulsé par NodeBB