Skip to content

Commit d9f3010

Browse files
committed
change code style for ai checks
1 parent 9a1a02c commit d9f3010

File tree

1 file changed

+65
-94
lines changed

1 file changed

+65
-94
lines changed

Apple-Music-Scraper/utils.py

Lines changed: 65 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,88 @@
11
import urllib.parse
2-
import requests, json
2+
import requests
3+
import json
34
from bs4 import BeautifulSoup
45

6+
57
def get_cover(url, width, height, format="jpg", crop_option=""):
68
"""
79
Generate a full Apple Music artwork URL with proper width, height, format, and crop settings.
8-
9-
Parameters
10-
----------
11-
url : str
12-
The original Apple Music artwork template URL containing `{w}`, `{h}`, `{f}`, `{c}`.
13-
width : int or str
14-
Target width of the image.
15-
height : int or str
16-
Target height of the image.
17-
format : str, optional
18-
Image format (jpg, png, etc.). Defaults to `"jpg"`.
19-
crop_option : str, optional
20-
Cropping mode used by Apple Music artwork URLs. Defaults to empty string.
21-
22-
Returns
23-
-------
24-
str
25-
Fully formatted artwork URL.
26-
27-
Notes
28-
-----
29-
Apple Music uses dynamic artwork URLs where dimensions and format are embedded
30-
in the URL as placeholders such as `{w}`, `{h}`, `{f}`, and `{c}`.
3110
"""
32-
new_url = url.replace("{w}", str(width))
33-
new_url = new_url.replace("{h}", str(height))
34-
new_url = new_url.replace("{c}", crop_option)
35-
new_url = new_url.replace("{f}", format)
36-
return new_url
11+
if not isinstance(url, str):
12+
return url
13+
14+
try:
15+
new_url = (
16+
url.replace("{w}", str(width))
17+
.replace("{h}", str(height))
18+
.replace("{c}", crop_option)
19+
.replace("{f}", format)
20+
)
21+
return new_url
22+
except (TypeError, AttributeError):
23+
return url
24+
3725

3826
def convert_album_to_song_url(album_url):
3927
"""
4028
Convert an Apple Music album-track URL into a direct Apple Music song URL.
41-
42-
Parameters
43-
----------
44-
album_url : str
45-
Full Apple Music album URL that contains a track ID via the query parameter `?i=...`.
46-
47-
Returns
48-
-------
49-
str or None
50-
Direct Apple Music song URL if `i` parameter exists.
51-
Otherwise, returns `None`.
52-
53-
Examples
54-
--------
55-
Input:
56-
https://music.apple.com/us/album/song-name/12345?i=67890
57-
58-
Output:
59-
https://music.apple.com/us/song/song-name/67890
60-
61-
Notes
62-
-----
63-
Apple Music album pages embed individual song IDs through the query parameter `i`,
64-
which must be extracted and placed into a `/song/` URL.
6529
"""
66-
parsed = urllib.parse.urlparse(album_url)
67-
query_params = urllib.parse.parse_qs(parsed.query)
68-
song_id = query_params.get('i', [None])[0]
30+
try:
31+
parsed = urllib.parse.urlparse(album_url)
32+
query_params = urllib.parse.parse_qs(parsed.query)
33+
song_id = query_params.get("i", [None])[0]
6934

70-
if not song_id:
71-
return None
35+
if not song_id:
36+
return None
37+
38+
parts = parsed.path.split("/")
39+
if len(parts) < 4:
40+
return None
7241

73-
parts = parsed.path.split('/')
74-
country = parts[1]
75-
title = parts[3]
42+
country = parts[1]
43+
title = parts[3]
44+
45+
return f"https://music.apple.com/{country}/song/{title}/{song_id}"
46+
47+
except (IndexError, KeyError, TypeError, AttributeError, ValueError):
48+
return None
7649

77-
return f"https://music.apple.com/{country}/song/{title}/{song_id}"
7850

7951
def get_all_singles(url="https://music.apple.com/us/artist/king-princess/1349968534"):
8052
"""
8153
Fetch all singles & EP URLs from an Apple Music artist page.
82-
83-
Parameters
84-
----------
85-
url : str, optional
86-
Base artist page URL. Defaults to the sample King Princess artist link.
87-
88-
Returns
89-
-------
90-
list[str]
91-
A list of Apple Music URLs for all singles & EPs for the artist.
92-
93-
Notes
94-
-----
95-
- Apple Music loads singles under the `/see-all?section=singles` endpoint.
96-
- This function retrieves the serialized server data, parses the `items` section,
97-
and extracts the correct song/EP URLs.
98-
- Used internally by `artist_scrape()`.
9954
"""
10055
result = []
101-
url = url+"/see-all?section=singles"
102-
103-
headers = {
104-
"User-Agent": "Mozilla/5.0"
105-
}
10656

107-
res = requests.get(url, headers=headers)
57+
full_url = f"{url}/see-all?section=singles"
58+
headers = {"User-Agent": "Mozilla/5.0"}
59+
60+
try:
61+
res = requests.get(full_url, headers=headers, timeout=10)
62+
res.raise_for_status()
63+
except requests.RequestException:
64+
return result
65+
10866
soup = BeautifulSoup(res.text, "html.parser")
109-
items = soup.find('script', {'id': 'serialized-server-data'})
110-
our_json = json.loads(items.text)
111-
112-
sections = our_json[0]['data']['sections'][0]['items']
113-
114-
for i in sections:
115-
result.append((i['segue']['actionMetrics']['data'][0]['fields']['actionUrl']))
116-
117-
return result
67+
script_tag = soup.find("script", {"id": "serialized-server-data"})
68+
if not script_tag:
69+
return result
70+
71+
try:
72+
data = json.loads(script_tag.text)
73+
sections = data[0]["data"]["sections"]
74+
if not sections:
75+
return result
76+
77+
items = sections[0].get("items", [])
78+
except (json.JSONDecodeError, KeyError, IndexError, TypeError):
79+
return result
80+
81+
for item in items:
82+
try:
83+
action_url = item["segue"]["actionMetrics"]["data"][0]["fields"]["actionUrl"]
84+
result.append(action_url)
85+
except (KeyError, IndexError, TypeError):
86+
continue
87+
88+
return result

0 commit comments

Comments
 (0)