-
-
Save TheMuellenator/c84616c21f0f9ce68c12c357d3e1c794 to your computer and use it in GitHub Desktop.
sp = spotipy.Spotify( | |
auth_manager=SpotifyOAuth( | |
scope="playlist-modify-private", | |
redirect_uri="http://example.com", | |
client_id=YOUR UNIQUE CLIENT ID, | |
client_secret= YOUR UNIQUE CLIENT SECRET, | |
show_dialog=True, | |
cache_path="token.txt" | |
) | |
) | |
user_id = sp.current_user()["id"] | |
date = input("Which year do you want to travel to? Type the date in this format YYYY-MM-DD: ") | |
song_uris = ["The list of", "song URIs", "you got by", "searching Spotify"] | |
playlist = sp.user_playlist_create(user=user_id, name=f"{date} Billboard 100", public=False) | |
# print(playlist) | |
sp.playlist_add_items(playlist_id=playlist["id"], items=song_uris) |
billboard site is not responding. pls help
I had to add very specified search criteria when fetching information from Billboard site:
song_names_spans = soup.select("ul li ul li h3", id_="title-of-a-story", class_="c-title")
v-- I also had issue creating the playlist to Spotify. Code below resolved my issue, thank you @grizzleswens ! --v
grizzleswens commented on Mar 5, 2024
Here is my code, it is working perfectly, I had to have a little bit of hand holding from chat gptimport requests from bs4 import BeautifulSoup import spotipy from spotipy.oauth2 import SpotifyOAuth
Set your Spotify app credentials
You will need to make a spotify web app to get this data, go to spotify dev tools
SPOTIPY_CLIENT_ID = 'YOUR CLIENT ID' SPOTIPY_CLIENT_SECRET = 'YOUR CLIENT SECRET' SPOTIPY_REDIRECT_URI = 'YOUR REDIRECT URI' SCOPE = 'playlist-modify-public user-read-private'
date = input("What date would you like to travel back in time to? YYYY-MM-DD") endpoint = f"https://www.billboard.com/charts/hot-100/{date}/"
Scrape web for top 100 songs
response = requests.get(endpoint) html_data = response.text
soup = BeautifulSoup(html_data, "html.parser")
songs = soup.select("li ul li h3") songs_titles = [song.getText().strip() for song in songs]
track_uris = []
Authenticate with Spotify
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIPY_CLIENT_ID, client_secret=SPOTIPY_CLIENT_SECRET, redirect_uri=SPOTIPY_REDIRECT_URI, scope=SCOPE))
Find track URIs
for song in songs_titles: try: results = sp.search(q=f"track:{song}", type="track") track_uri = results['tracks']['items'][0]['uri'] track_uris.append(track_uri) except IndexError: continue
# Authenticate with Spotify
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=SPOTIPY_CLIENT_ID, client_secret=SPOTIPY_CLIENT_SECRET, redirect_uri=SPOTIPY_REDIRECT_URI, scope=SCOPE))
Get current user's profile data
user_id = sp.current_user()['id']
Create a new playlist for the current user
playlist_name = f"Billboard top songs on {date}" playlist_description = "Created with Python" playlist = sp.user_playlist_create(user=user_id, name=playlist_name, description=playlist_description)
Get the playlist ID
playlist_id = playlist['id']
Add tracks to the playlist
sp.playlist_add_items(playlist_id=playlist_id, items=track_uris)
print(f"Playlist created and tracks added. Playlist ID: {playlist_id}")
To add the tracks to the playlist I used another spotipy method, I can't find the one in the solution in the documentation. According to PyCharm that method also doesn't exist. Here is my code I used:
``
import requests
from bs4 import BeautifulSoup
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import os
from dotenv import load_dotenv
load_dotenv()
BILLBOARD_ENDPOINT= "https://www.billboard.com/charts/hot-100/"
BILLBOARD_HEADER = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0"}
# entered a fixed date for testing purposes
# date = input("Which year do you want to travel to? Type the date in this format YYYY-MM-DD:")
date = "2022-12-12"
response = requests.get(url=f"{BILLBOARD_ENDPOINT}{date}",headers=BILLBOARD_HEADER)
soup = BeautifulSoup(response.text, "html.parser")
songs = soup.find_all(name="h3", class_="c-title a-no-trucate a-font-primary-bold-s u-letter-spacing-0021 lrv-u-font-size-18@tablet lrv-u-font-size-16 u-line-height-125 u-line-height-normal@mobile-max a-truncate-ellipsis u-max-width-330 u-max-width-230@tablet-only")
top_100_songs = []
for song in songs:
title = song.getText().strip()
top_100_songs.append(title)
sp = spotipy.Spotify(
auth_manager=SpotifyOAuth(
scope="playlist-modify-private",
redirect_uri="http://example.com",
client_id=os.environ["SPOTIPY_CLIENT_ID"],
client_secret=os.environ["SPOTIPY_CLIENT_SECRET"],
show_dialog=True,
cache_path="token.txt",
username="***********"
)
)
user_id = sp.current_user()["id"]
track_uri_list = []
for song in top_100_songs:
search = sp.search(q=song,type="track")
try:
track_uri_list.append(search["tracks"]["items"][0]["uri"])
except IndexError:
print("Track not found")
playlist_name = f"{date} Billboard 100"
playlist = sp.user_playlist_create(user_id, playlist_name, public=False, description=f"Billboard top 10 from {date}")
playlist_id = playlist["id"]
print(f"playlist created with id {playlist_id}")
sp.user_playlist_add_tracks(user=user_id, playlist_id=playlist_id, tracks=track_uri_list)
print("tracks added")
``
This is going to be my first comment ever in any course I've ever done. If You are struggling, please use this code, it has error handling, it has log it has prints, I went freaked out and went all over hahaha:
import requests
from bs4 import BeautifulSoup
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from spotipy.exceptions import SpotifyException
import logging
import time
Spotify credentials
SPOTIFY_CLIENT_SECRET = "YOURSECRET"
SPOTIFY_CLIENT_ID = "YOURID"
iN SPOTIFY I USED THE MAC URL OF MY PC WITH PORT 3000 for the authorization
REDIRECT_URI = "http://127.0.0.1:3000"
--- Logging Setup ---
logging.basicConfig(
filename='playlist_log.txt',
filemode='a',
format='%(asctime)s - %(levelname)s - %(message)s',
level=logging.INFO
)
--- Get User Input ---
date = input("Enter the date (YYYY-MM-DD): ")
playlist_name = input("Enter a name for your Spotify playlist: ")
logging.info(f"User input date: {date}, playlist name: {playlist_name}")
--- Billboard Scraper ---
def get_billboard_hot_100(date):
url = f"https://www.billboard.com/charts/hot-100/{date}"
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/114.0.0.0 Safari/537.36"
)
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
except requests.exceptions.HTTPError as e:
logging.error(f"HTTP Error while accessing Billboard: {e}")
print(f"❌ Billboard page returned {response.status_code}. Try another date.")
return []
except requests.exceptions.RequestException as e:
logging.error(f"Request failed: {e}")
print("❌ Failed to fetch Billboard page.")
return []
soup = BeautifulSoup(response.text, "html.parser")
songs = []
# Billboard class sets
target_classes = {
'c-title', 'a-no-trucate', 'a-font-primary-bold-s',
'u-letter-spacing-0021', 'lrv-u-font-size-18@tablet',
'lrv-u-font-size-16', 'u-line-height-125',
'u-line-height-normal@mobile-max', 'a-truncate-ellipsis',
'u-max-width-330', 'u-max-width-230@tablet-only'
}
target_classes_top = {
'c-title', 'a-no-trucate', 'a-font-primary-bold-s',
'u-letter-spacing-0021', 'u-font-size-23@tablet',
'lrv-u-font-size-16', 'u-line-height-125',
'u-line-height-normal@mobile-max', 'a-truncate-ellipsis',
'u-max-width-245', 'u-max-width-230@tablet-only',
'u-letter-spacing-0028@tablet'
}
def class_matcher(tag, class_set):
return (
tag.name == "h3" and
tag.get("class") and
set(tag.get("class")).issuperset(class_set)
)
# Top 1 song using lambda to match the exact classes
try:
top_tag = soup.find(lambda tag: class_matcher(tag, target_classes_top))
if top_tag:
top_title = top_tag.get_text(strip=True)
top_artist_tag = top_tag.find_parent("li").find("span", class_="c-label")
top_artist = top_artist_tag.get_text(strip=True) if top_artist_tag else "Various Artists"
songs.append((top_title, top_artist))
except Exception as e:
logging.warning(f"Failed to parse top song: {e}")
# Songs 2–100
try:
all_h3s = soup.find_all(lambda tag: class_matcher(tag, target_classes))
for tag in all_h3s:
title = tag.get_text(strip=True)
artist_tag = tag.find_parent("li").find("span", class_="c-label")
artist = artist_tag.get_text(strip=True) if artist_tag else "Various Artists"
songs.append((title, artist))
except Exception as e:
logging.error(f"Failed to parse song list: {e}")
return songs
--- Spotify Authentication ---
try:
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id=SPOTIFY_CLIENT_ID,
client_secret=SPOTIFY_CLIENT_SECRET,
redirect_uri=REDIRECT_URI,
scope="playlist-modify-private"
))
user_id = sp.current_user()["id"]
except SpotifyException as e:
logging.critical(f"Spotify authentication failed: {e}")
print("❌ Spotify login failed. Check credentials or scope.")
exit(1)
--- Fetch Songs ---
try:
songs = get_billboard_hot_100(date)
logging.info(f"Fetched {len(songs)} songs from Billboard.")
except Exception as e:
logging.critical(f"Unexpected error fetching Billboard songs: {e}")
print("❌ Something went wrong getting Billboard data.")
exit(1)
if not songs:
print("
exit()
--- Search Spotify for Songs ---
track_uris = []
for title, artist in songs:
query = f"{title} {artist}"
try:
result = sp.search(q=query, type="track", limit=1)
items = result["tracks"]["items"]
if items:
uri = items[0]["uri"]
track_uris.append(uri)
print(f"✅ Found: {title} by {artist}")
else:
logging.warning(f"❌ Not found: {title} by {artist}")
except SpotifyException as e:
logging.error(f"Spotify search failed for '{query}': {e}")
continue
time.sleep(0.2) # prevent rate limiting
--- Create Playlist and Add Tracks ---
if track_uris:
try:
playlist = sp.user_playlist_create(user=user_id, name=playlist_name, public=False)
sp.playlist_add_items(playlist_id=playlist["id"], items=track_uris)
print(f"\n🎉 Playlist '{playlist_name}' created with {len(track_uris)} tracks!")
logging.info(f"Playlist '{playlist_name}' created with {len(track_uris)} tracks.")
except SpotifyException as e:
logging.error(f"Failed to create playlist or add songs: {e}")
print("❌ Playlist creation or track addition failed.")
else:
print("\n
logging.warning("No Spotify tracks found; playlist not created.")
I have added few more features:
- get the list of playlists in a user profile
- check if there is an empty playlist and if yes, get its 'id'
- if no playlists exist or if no empty playlists exist, create a new playlist and get its id
- time taken to execute the program completely
This way we can have new playlist on every run.
Note: Spotify takes some time to report the proper track count in a playlist. So, if you create a new empty playlist, add some songs to it, and immediately run the code again, the previously created playlist will be reported as empty. I think it takes roughly 15sec to get the updated count.
`
GOAL - to create a spotify playlist of top 100 songs on billboard.com on a selected day
import requests
from bs4 import BeautifulSoup
import time
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import pprint
spotify_client_id = "..."
spotify_client_secret = "..."
spotify_redirect_uri = "https://example.com/"
def get_top_100_titles(selected_date) -> list:
"""
Fetches the top 100 titles for a selected date from billboard.com and returns
:return: list of top 100 titles
"""
print(f"Getting top 100 titles on {selected_date} from billboard...")
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0"}
billboard_url = "https://www.billboard.com/charts/hot-100/" + selected_date.strip()
response = requests.get(url=billboard_url, headers=header)
response.raise_for_status()
website = response.text
soup = BeautifulSoup(website, "html.parser")
# list_items = soup.find_all(name="li", class_="o-chart-results-list__item")
list_items = soup.select("li ul li h3")
titles = [item.string.strip() for item in list_items]
# for item in list_items:
# title_h3 = item.find(name="h3", attrs={"class":"c-title"})
# if title_h3:
# titles.append(title_h3.string.strip())
return titles
def write_data(selected_date, data: list) -> None:
"""
Writes the data to a text file
:param selected_date: user selected date
:param data: list
:return: None
"""
print("Adding the top 100 songs to the file...")
with open("top_100.txt", "w") as file:
file.write(f"{selected_date}\n")
for i in range(len(data)):
file.write(f"{i + 1}. {data[i]}\n")
def humanize_time(seconds) -> None:
intervals = [("d", 86400), ("h", 3600), ("m", 60)]
parts = []
if seconds:
for label, count in intervals:
value, seconds = divmod(seconds, count)
if value:
parts.append(f"{value:.0f}{label}")
parts.append(f"{seconds:.02f}s")
print(" ".join(parts))
def add_to_playlist(date, titles_to_add):
print("Authenticating with Spotify...")
# steps to add the title to the user's spotify playlist
# 1. get client_id, client_secret from spotify
# 2. get authorization token from spotify using spotipy
# spotify authorization
# playlist-modify-private
# scope = "user-library-read"
scope = "playlist-modify-public"
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope, client_id=spotify_client_id,
client_secret=spotify_client_secret, redirect_uri=spotify_redirect_uri, show_dialog=True, cache_path="token.txt", username="vgst cof"))
user_id = sp.current_user()["id"]
# 3. get an empty playlist id from spotify
# get the list of playlists in a user profile
print("Fetching list of playlists...")
playlist_search_results = sp.current_user_playlists()["items"]
# check if there are any empty playlists and get its id
empty_playlist_id = None
if playlist_search_results:
print(f"{len(playlist_search_results)} playlists exist")
# there are playlists in the user profile
for playlist in playlist_search_results:
no_of_tracks = int(playlist["tracks"]["total"])
if not no_of_tracks:
print(no_of_tracks)
empty_playlist_id = playlist["id"]
empty_playlist_name = playlist["name"]
print(f"Empty playlist name: {empty_playlist_name}")
break
if not playlist_search_results or not empty_playlist_id:
print("No playlists or no empty playlists exist, creating a new playlist...")
# if there are no playlists or if there are no empty playlists, create a new playlist
new_empty_playlist = sp.user_playlist_create(user=user_id, name=f"Top 100 {date}")
empty_playlist_id = new_empty_playlist["id"]
empty_playlist_name = new_empty_playlist["name"]
print(f"New empty playlist name: {empty_playlist_name}")
# 4. get the id of the title
print("Adding tracks to the the playlist", end="")
titles_with_ids = []
for title in titles_to_add:
print(".", end="")
search_results = sp.search(q="track:" + title, type="track")["tracks"]["items"]
if search_results:
# if the title exists in spotify db
title_id = search_results[0]["id"]
titles_with_ids.append(title_id)
else:
print(title, "does not exist in Spotify. Skipped.")
# 5. add the title to the user's playlist
sp.playlist_add_items(playlist_id=empty_playlist_id, items=titles_with_ids)
#--------------------#--------------------#
get the date from the user
user_chosen_date = input("Which year do you want to travel to? Type the date in YYYY-MM-DD: ")
to track the time for program execution
start_t = time.time()
get the top 100 songs/titles for the selected date
top_100_titles = get_top_100_titles(user_chosen_date)
if top_100_titles:
# write the titles to a text file
write_data(user_chosen_date, top_100_titles)
# add tracks to the user's playlist
add_to_playlist(user_chosen_date, top_100_titles)
end_t = time.time()
humanize_time(end_t - start_t)
`
This is my version and it works for me having as an end result adding a playlist to my Spotify account.
mport spotipy
from spotipy.oauth2 import SpotifyOAuth
import requests
from bs4 import BeautifulSoup
from dotenv import load_dotenv
import os
import pprint
Top 100 songs travel to memory lane
year_to_travel = input("What year would you like to travel? Please type the date on this format YYYY-MM-DD\n")
url = f"https://www.billboard.com/charts/hot-100/{year_to_travel}"
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0"
}
response = requests.get(url=url, headers=header)
soup = BeautifulSoup(response.content, "html.parser")
print(soup.prettify())
with open("page_to_check.html", "w", encoding='utf-8') as file:
file.write(str(soup))
song_names_spans = soup.select("li ul li h3")
print(song_names_spans)
using a list comprehension
songs_names_list = [song.getText().strip() for song in song_names_spans]
print(songs_names_list)
load_dotenv('.env')
CLIENT_ID = os.getenv("SPOTIPY_CLIENT_ID")
CLIENT_SECRET = os.getenv("SPOTIPY_CLIENT_SECRET")
REDIRECT_URI = os.getenv("SPOTIPY_REDIRECT_URI")
OAUTH_AUTHORIZE_URL = 'https://accounts.spotify.com/authorize'
OAUTH_TOKEN_URL = 'https://accounts.spotify.com/api/token'
scope = "playlist-modify-private", "Playlist-modify_public"
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
redirect_uri=REDIRECT_URI,
scope="playlist-modify-private",
show_dialog=True,
cache_path="token.txt",
))
track_uris = []
for song_name in songs_names_list:
results = sp.search(q=song_name, type="track", limit=1)
tracks = results.get('tracks', {}).get('items', [])
# print(results)
try:
track_uri = tracks[0]["uri"]
track_uris.append(track_uri)
except IndexError:
print(f"{song_name} doesn't exist in Spotify. Skipped.")
pprint.pp(track_uris)
Create a private playlist
User_id = sp.current_user()["id"]
playlist_name = "My Python Playlist(Songs Names Only)"
playlist = sp.user_playlist_create(user=User_id, name=playlist_name, public=False)
pprint.pp(playlist)
add tracks to the playlist
if track_uris:
sp.playlist_add_items(playlist_id=playlist['id'], items=track_uris)
print(f"Playlist'{playlist_name}'has been created successfully!")
else:
print("No valid tracks found. Playlist not created")