11from bs4 import BeautifulSoup
2- import requests , json
2+ import requests
3+ import json
34from utils import convert_album_to_song_url , get_cover , get_all_singles
45
56
@@ -51,7 +52,10 @@ def room_scrape(link="https://music.apple.com/us/room/6748797380"):
5152
5253 for item in items :
5354 try :
54- action_url = item ["playAction" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
55+ action_url = (
56+ item ["playAction" ]["actionMetrics" ]
57+ ["data" ][0 ]["fields" ]["actionUrl" ]
58+ )
5559 song_url = convert_album_to_song_url (action_url )
5660 if song_url :
5761 result .append (song_url )
@@ -61,7 +65,12 @@ def room_scrape(link="https://music.apple.com/us/room/6748797380"):
6165 return result
6266
6367
64- def playlist_scrape (link = "https://music.apple.com/us/playlist/new-music-daily/pl.2b0e6e332fdf4b7a91164da3162127b5" ):
68+ def playlist_scrape (
69+ link = (
70+ "https://music.apple.com/us/playlist"
71+ "/new-music-daily/pl.2b0e6e332fdf4b7a91164da3162127b5"
72+ ),
73+ ):
6574 """
6675 Scrape an Apple Music playlist and extract all track URLs.
6776
@@ -108,7 +117,10 @@ def playlist_scrape(link="https://music.apple.com/us/playlist/new-music-daily/pl
108117
109118 for item in items :
110119 try :
111- action_url = item ["playAction" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
120+ action_url = (
121+ item ["playAction" ]["actionMetrics" ]
122+ ["data" ][0 ]["fields" ]["actionUrl" ]
123+ )
112124 song_url = convert_album_to_song_url (action_url )
113125 if song_url :
114126 result .append (song_url )
@@ -208,7 +220,14 @@ def search(keyword="sasha sloan"):
208220 artwork_dict .get ("width" , 0 ),
209221 artwork_dict .get ("height" , 0 ),
210222 )
211- result ["albums" ].append ({"title" : title , "artist" : artist , "url" : url , "image" : img })
223+ result ["albums" ].append (
224+ {
225+ "title" : title ,
226+ "artist" : artist ,
227+ "url" : url ,
228+ "image" : img
229+ }
230+ )
212231 except (KeyError , TypeError , IndexError ):
213232 continue
214233
@@ -224,7 +243,14 @@ def search(keyword="sasha sloan"):
224243 artwork_dict .get ("width" , 0 ),
225244 artwork_dict .get ("height" , 0 ),
226245 )
227- result ["songs" ].append ({"title" : title , "artist" : artist , "url" : url , "image" : img })
246+ result ["songs" ].append (
247+ {
248+ "title" : title ,
249+ "artist" : artist ,
250+ "url" : url ,
251+ "image" : img
252+ }
253+ )
228254 except (KeyError , TypeError , IndexError ):
229255 continue
230256
@@ -240,7 +266,14 @@ def search(keyword="sasha sloan"):
240266 artwork_dict .get ("width" , 0 ),
241267 artwork_dict .get ("height" , 0 ),
242268 )
243- result ["playlists" ].append ({"title" : title , "artist" : artist , "url" : url , "image" : img })
269+ result ["playlists" ].append (
270+ {
271+ "title" : title ,
272+ "artist" : artist ,
273+ "url" : url ,
274+ "image" : img
275+ }
276+ )
244277 except (KeyError , TypeError , IndexError ):
245278 continue
246279
@@ -256,7 +289,14 @@ def search(keyword="sasha sloan"):
256289 artwork_dict .get ("width" , 0 ),
257290 artwork_dict .get ("height" , 0 ),
258291 )
259- result ["videos" ].append ({"title" : title , "artist" : artist , "url" : url , "image" : img })
292+ result ["videos" ].append (
293+ {
294+ "title" : title ,
295+ "artist" : artist ,
296+ "url" : url ,
297+ "image" : img
298+ }
299+ )
260300 except (KeyError , TypeError , IndexError ):
261301 continue
262302
@@ -334,19 +374,31 @@ def song_scrape(url="https://music.apple.com/us/song/california/1821538031"):
334374 result ["album" ]["title" ] = item .get ("album" , "" )
335375
336376 try :
337- result ["album" ]["url" ] = item ["albumLinks" ][0 ]["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
377+ result ["album" ]["url" ] = (
378+ item ["albumLinks" ][0 ]["segue" ]["actionMetrics" ]
379+ ["data" ][0 ]["fields" ]["actionUrl" ]
380+ )
338381 except (KeyError , IndexError , TypeError ):
339382 pass
340383
341384 result ["artist" ]["title" ] = item .get ("artists" , "" )
342385
343386 try :
344- result ["artist" ]["url" ] = item ["artistLinks" ][0 ]["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
387+ result ["artist" ]["url" ] = (
388+ item ["artistLinks" ][0 ]["segue" ]["actionMetrics" ]
389+ ["data" ][0 ]["fields" ]["actionUrl" ]
390+ )
345391 except (KeyError , IndexError , TypeError ):
346392 pass
347393
348394 try :
349- json_tag = soup .find ("script" , {"id" : "schema:song" , "type" : "application/ld+json" })
395+ json_tag = soup .find (
396+ "script" ,
397+ {
398+ "id" : "schema:song" ,
399+ "type" : "application/ld+json"
400+ }
401+ )
350402 schema_data = json .loads (json_tag .string )
351403 result ["preview-url" ] = schema_data ["audio" ]["audio" ]["contentUrl" ]
352404 except (AttributeError , KeyError , TypeError , json .JSONDecodeError ):
@@ -471,15 +523,21 @@ def album_scrape(url="https://music.apple.com/us/album/1965/1817707266?i=1817707
471523
472524 # CAPTION
473525 try :
474- result ["caption" ] = item .get ("modalPresentationDescriptor" , {}).get ("paragraphText" , "" )
526+ result ["caption" ] = item .get (
527+ "modalPresentationDescriptor" ,
528+ {}
529+ ).get ("paragraphText" , "" )
475530 except Exception :
476531 pass
477532
478533 # ARTIST
479534 try :
480535 sl = item .get ("subtitleLinks" , [])[0 ]
481536 result ["artist" ]["title" ] = sl .get ("title" , "" )
482- result ["artist" ]["url" ] = sl ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
537+ result ["artist" ]["url" ] = (
538+ sl ["segue" ]["actionMetrics" ]
539+ ["data" ][0 ]["fields" ]["actionUrl" ]
540+ )
483541 except Exception :
484542 pass
485543
@@ -539,7 +597,12 @@ def album_scrape(url="https://music.apple.com/us/album/1965/1817707266?i=1817707
539597 return result
540598
541599
542- def video_scrape (url = "https://music.apple.com/us/music-video/gucci-mane-visualizer/1810547026" ):
600+ def video_scrape (
601+ url = (
602+ "https://music.apple.com/us/music-video/"
603+ "gucci-mane-visualizer/1810547026"
604+ ),
605+ ):
543606 """
544607 Scrape Apple Music music-video page and extract metadata + video file URL.
545608
@@ -627,13 +690,22 @@ def video_scrape(url="https://music.apple.com/us/music-video/gucci-mane-visualiz
627690 try :
628691 sl = item .get ("subtitleLinks" , [])[0 ]
629692 result ["artist" ]["title" ] = sl .get ("title" , "" )
630- result ["artist" ]["url" ] = sl ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
693+ result ["artist" ]["url" ] = (
694+ sl ["segue" ]["actionMetrics" ]
695+ ["data" ][0 ]["fields" ]["actionUrl" ]
696+ )
631697 except Exception :
632698 pass
633699
634700 # VIDEO URL
635701 try :
636- json_tag = soup .find ("script" , {"id" : "schema:music-video" , "type" : "application/ld+json" })
702+ json_tag = soup .find (
703+ "script" ,
704+ {
705+ "id" : "schema:music-video" ,
706+ "type" : "application/ld+json"
707+ }
708+ )
637709 schema_data = json .loads (json_tag .string )
638710 result ["video-url" ] = schema_data ["video" ]["contentUrl" ]
639711 except (AttributeError , KeyError , TypeError , json .JSONDecodeError ):
@@ -782,7 +854,10 @@ def artist_scrape(url="https://music.apple.com/us/artist/king-princess/134996853
782854
783855 # LATEST
784856 try :
785- result ["latest" ] = latest_and_top ["pinnedLeadingItem" ]["item" ]["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
857+ result ["latest" ] = (
858+ latest_and_top ["pinnedLeadingItem" ]["item" ]["segue" ]
859+ ["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
860+ )
786861 except Exception :
787862 pass
788863
@@ -962,23 +1037,29 @@ def test_all_functions():
9621037
9631038 print ("\n === TEST: album_scrape ===" )
9641039 try :
965- album = album_scrape ("https://music.apple.com/us/album/1965/1817707266?i=1817707585" )
1040+ album = album_scrape (
1041+ "https://music.apple.com/us/album/1965/1817707266?i=1817707585"
1042+ )
9661043 print ("Album title:" , album .get ("title" ))
9671044 print ("Songs:" , len (album .get ("songs" , [])))
9681045 except Exception as e :
9691046 print ("album_scrape ERROR:" , e )
9701047
9711048 print ("\n === TEST: video_scrape ===" )
9721049 try :
973- video = video_scrape ("https://music.apple.com/us/music-video/gucci-mane-visualizer/1810547026" )
1050+ video = video_scrape (
1051+ "https://music.apple.com/us/music-video/gucci-mane-visualizer/1810547026"
1052+ )
9741053 print ("Video title:" , video .get ("title" ))
9751054 print ("Video URL exists:" , bool (video .get ("video-url" )))
9761055 except Exception as e :
9771056 print ("video_scrape ERROR:" , e )
9781057
9791058 print ("\n === TEST: artist_scrape ===" )
9801059 try :
981- artist = artist_scrape ("https://music.apple.com/us/artist/king-princess/1349968534" )
1060+ artist = artist_scrape (
1061+ "https://music.apple.com/us/artist/king-princess/1349968534"
1062+ )
9821063 print ("Artist title:" , artist .get ("title" ))
9831064 print ("Top songs:" , len (artist .get ("top" , [])))
9841065 print ("Albums:" , len (artist .get ("albums" , [])))
@@ -987,3 +1068,5 @@ def test_all_functions():
9871068 print ("artist_scrape ERROR:" , e )
9881069
9891070 print ("\n === ALL TESTS COMPLETED ===" )
1071+
1072+ test_all_functions ()
0 commit comments