Récupérer une liste de lecture Apple


  • Prédateur

    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 classe spread
    • 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 fonction map, 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 petit sleep 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


Log in to reply