import re import requests def resolve_spotify_track(url: str) -> dict: """ Scrapes a public Spotify track page to extract the song title and artist. Returns: {"title": str, "artist": str} or None if resolution fails. """ # Regex to extract track ID match = re.search(r"track/([a-zA-Z0-9]+)", url) if not match: return None headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } try: response = requests.get(url, headers=headers, timeout=10) if response.status_code != 200: return None html = response.text # Try og:title and og:description or title tag # og:title typically has the song title title_match = re.search(r'= 2: # Often: "Song · Artist · Year" or "Artist · Song · [etc]" # Let's verify which one is the title. # If the first part matches the og:title, then the second part is the artist! if title and parts[0].lower() == title.lower(): artist = parts[1] elif title and parts[1].lower() == title.lower(): artist = parts[0] else: artist = parts[1] else: # Fallback: check if description says "Listen to [Song] on Spotify. [Artist] · Song · [Year]" listen_match = re.search(r"Listen to\s+([^\s]+)\s+on Spotify\.\s+([^\·]+)", desc) if listen_match: artist = listen_match.group(2).strip() # If still not found, try a simple title parse if not title: html_title = re.search(r"([^<]+)", html) if html_title: t_content = html_title.group(1) # Usually: "Song Name - song and artist by Artist | Spotify" t_parts = t_content.split(" | ") if len(t_parts) > 0: title = t_parts[0].replace(" - song and artist by ", " - ") # Clean up common spotify suffix / prefix if title: title = re.sub(r"\s-\s.*$", "", title) # remove everything after " - " if not title: return None return { "title": title, "artist": artist or "Unknown Artist" } except Exception as e: print(f"Error resolving Spotify metadata: {e}") return None # Simple testing hook if __name__ == "__main__": test_url = "https://open.spotify.com/track/4PTG3Z6ehGkBF3zI7YSpA0" print(resolve_spotify_track(test_url))