44from utils import convert_album_to_song_url , get_cover , get_all_singles
55
66
7+ def safe_action_url (item ):
8+ try :
9+ # segue-based URLs (most items)
10+ return item ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
11+ except Exception :
12+ pass
13+
14+ try :
15+ # fallback: plain contentDescriptor
16+ return item ["contentDescriptor" ]["url" ]
17+ except Exception :
18+ return None
19+
20+
21+ def find_section (sections , key ):
22+ for sec in sections :
23+ if key in sec .get ("id" , "" ):
24+ return sec
25+ return None
26+
27+
28+ def append_urls_from_section (section , target_list ):
29+ if not section :
30+ return
31+ for it in section .get ("items" , []):
32+ url = safe_action_url (it )
33+ if url :
34+ target_list .append (url )
35+
36+
737def room_scrape (link = "https://music.apple.com/us/room/6748797380" ):
838 """
939 Scrape a shared Apple Music room and extract song URLs.
@@ -407,11 +437,9 @@ def song_scrape(url="https://music.apple.com/us/song/california/1821538031"):
407437 try :
408438 more_items = sections [- 1 ]["items" ]
409439 for m in more_items :
410- try :
411- url = m [ "segue" ][ "actionMetrics" ][ "data" ][ 0 ][ "fields" ][ "actionUrl" ]
440+ url = safe_action_url ( m )
441+ if url :
412442 result ["more" ].append (url )
413- except (KeyError , IndexError , TypeError ):
414- continue
415443 except (KeyError , IndexError , TypeError ):
416444 pass
417445
@@ -563,23 +591,19 @@ def album_scrape(url="https://music.apple.com/us/album/1965/1817707266?i=1817707
563591
564592 more_items = sections [more_index ].get ("items" , [])
565593 for m in more_items :
566- try :
567- url = m [ "segue" ][ "actionMetrics" ][ "data" ][ 0 ][ "fields" ][ "actionUrl" ]
594+ url = safe_action_url ( m )
595+ if url :
568596 result ["more" ].append (url )
569- except Exception :
570- continue
571597 except Exception :
572598 pass
573599
574600 # SIMILAR
575601 try :
576602 sim_items = sections [similar_index ].get ("items" , [])
577603 for s in sim_items :
578- try :
579- url = s [ "segue" ][ "actionMetrics" ][ "data" ][ 0 ][ "fields" ][ "actionUrl" ]
604+ url = safe_action_url ( s )
605+ if url :
580606 result ["similar" ].append (url )
581- except Exception :
582- continue
583607 except Exception :
584608 pass
585609
@@ -670,11 +694,9 @@ def video_scrape(
670694 similar = sec
671695
672696 # TITLE
673- try :
674- item = music_video_header ["items" ][0 ]
675- result ["title" ] = item .get ("title" , "" )
676- except Exception :
677- pass
697+ item = (music_video_header or {}).get ("items" , [{}])[0 ]
698+ result ["title" ] = item .get ("title" , "" )
699+
678700
679701 # IMAGE
680702 try :
@@ -715,22 +737,18 @@ def video_scrape(
715737 # MORE BY ARTIST
716738 try :
717739 for m in more .get ("items" , []):
718- try :
719- url = m [ "segue" ][ "actionMetrics" ][ "data" ][ 0 ][ "fields" ][ "actionUrl" ]
740+ url = safe_action_url ( m )
741+ if url :
720742 result ["more" ].append (url )
721- except Exception :
722- continue
723743 except Exception :
724744 pass
725745
726746 # SIMILAR
727747 try :
728748 for s in similar .get ("items" , []):
729- try :
730- url = s [ "segue" ][ "actionMetrics" ][ "data" ][ 0 ][ "fields" ][ "actionUrl" ]
749+ url = safe_action_url ( s )
750+ if url :
731751 result ["similar" ].append (url )
732- except Exception :
733- continue
734752 except Exception :
735753 pass
736754
@@ -806,39 +824,16 @@ def artist_scrape(url="https://music.apple.com/us/artist/king-princess/134996853
806824 except (KeyError , IndexError , json .JSONDecodeError ):
807825 return result
808826
809- artist_detail = None
810- latest_and_top = None
811- albums = None
812- playlists = None
813- videos = None
814- appears_on = None
815- more_to_see = None
816- more_to_hear = None
817- bio = None
818- similar = None
819-
820- for sec in sections :
821- sec_id = sec .get ("id" , "" )
822- if "artist-detail-header-section" in sec_id :
823- artist_detail = sec
824- elif "latest-release-and-top-songs" in sec_id :
825- latest_and_top = sec
826- elif "full-albums" in sec_id :
827- albums = sec
828- elif "playlists" in sec_id :
829- playlists = sec
830- elif "music-videos" in sec_id :
831- videos = sec
832- elif "appears-on" in sec_id :
833- appears_on = sec
834- elif "more-to-see" in sec_id :
835- more_to_see = sec
836- elif "more-to-hear" in sec_id :
837- more_to_hear = sec
838- elif "artist-bio" in sec_id :
839- bio = sec
840- elif "similar-artists" in sec_id :
841- similar = sec
827+ artist_detail = find_section (sections , "artist-detail-header-section" )
828+ latest_and_top = find_section (sections , "latest-release-and-top-songs" )
829+ albums = find_section (sections , "full-albums" )
830+ playlists = find_section (sections , "playlists" )
831+ videos = find_section (sections , "music-videos" )
832+ appears_on = find_section (sections , "appears-on" )
833+ more_to_see = find_section (sections , "more-to-see" )
834+ more_to_hear = find_section (sections , "more-to-hear" )
835+ bio = find_section (sections , "artist-bio" )
836+ similar = find_section (sections , "similar-artists" )
842837
843838 # HEADER
844839 try :
@@ -863,106 +858,28 @@ def artist_scrape(url="https://music.apple.com/us/artist/king-princess/134996853
863858 pass
864859
865860 # TOP SONGS
866- try :
867- for it in latest_and_top .get ("items" , []):
868- try :
869- result ["top" ].append (
870- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
871- )
872- except Exception :
873- continue
874- except Exception :
875- pass
861+ append_urls_from_section (latest_and_top , result ["top" ])
876862
877863 # ALBUMS
878- try :
879- for it in albums .get ("items" , []):
880- try :
881- result ["albums" ].append (
882- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
883- )
884- except Exception :
885- continue
886- except Exception :
887- pass
888-
889- # SINGLES & EPs
890- try :
891- result ["singles_and_EP" ] = get_all_singles (url )
892- except Exception :
893- pass
864+ append_urls_from_section (albums , result ["albums" ])
894865
895866 # PLAYLISTS
896- try :
897- for it in playlists .get ("items" , []):
898- try :
899- result ["playlists" ].append (
900- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
901- )
902- except Exception :
903- continue
904- except Exception :
905- pass
867+ append_urls_from_section (playlists , result ["playlists" ])
906868
907869 # VIDEOS
908- try :
909- for it in videos .get ("items" , []):
910- try :
911- result ["videos" ].append (
912- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
913- )
914- except Exception :
915- continue
916- except Exception :
917- pass
870+ append_urls_from_section (videos , result ["videos" ])
918871
919- # SIMILAR ARTISTS
920- try :
921- for it in similar .get ("items" , []):
922- try :
923- result ["similar" ].append (
924- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
925- )
926- except Exception :
927- continue
928- except Exception :
929- pass
872+ # SIMILAR
873+ append_urls_from_section (similar , result ["similar" ])
930874
931875 # APPEARS ON
932- try :
933- for it in appears_on .get ("items" , []):
934- try :
935- result ["appears_on" ].append (
936- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
937- )
938- except Exception :
939- continue
940- except Exception :
941- pass
876+ append_urls_from_section (appears_on , result ["appears_on" ])
942877
943878 # MORE TO SEE
944- try :
945- for it in more_to_see .get ("items" , []):
946- try :
947- result ["more_to_see" ].append (
948- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
949- )
950- except Exception :
951- continue
952- except Exception :
953- pass
879+ append_urls_from_section (more_to_see , result ["more_to_see" ])
954880
955881 # MORE TO HEAR
956- try :
957- for it in more_to_hear .get ("items" , []):
958- try :
959- result ["more_to_hear" ].append (
960- it ["segue" ]["actionMetrics" ]["data" ][0 ]["fields" ]["actionUrl" ]
961- )
962- except Exception :
963- continue
964- except Exception :
965- pass
882+ append_urls_from_section (more_to_hear , result ["more_to_hear" ])
966883
967884 # ABOUT
968885 try :
@@ -1068,3 +985,6 @@ def test_all_functions():
1068985 print ("artist_scrape ERROR:" , e )
1069986
1070987 print ("\n === ALL TESTS COMPLETED ===" )
988+
989+
990+ test_all_functions ()
0 commit comments