Skip to content

Instantly share code, notes, and snippets.

@TheMuellenator
Forked from angelabauer/main.py
Last active May 6, 2024 15:46
Show Gist options
  • Save TheMuellenator/c84616c21f0f9ce68c12c357d3e1c794 to your computer and use it in GitHub Desktop.
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)
@Tejuzz
Copy link

Tejuzz commented Aug 29, 2023

PLEASE I NEED HELP WHY THIS CODE DOESN'T WORK FOR ME?

import requests from bs4 import BeautifulSoup import spotipy from spotipy.oauth2 import SpotifyOAuth

CLIENT_ID = "9067a23713c34ea68d7276265816c720" CLIENT_SECRET = "334e6b70064546b092ad6b355ec171db"

url = "https://www.billboard.com/charts/hot-100/"

date = input("Which year do you want to travel to? Type the date in this Format YY-MM-DD.")

response = requests.get(f"{url}{date}") web = response.text

soup = BeautifulSoup(web, "html.parser")

musics = soup.find_all("h3", "a-no-trucate") music_titles = [] for music in musics: title = music.get_text().strip() music_titles.append(title)

sp = spotipy.Spotify( auth_manager=SpotifyOAuth( scope="playlist-modify-private", redirect_uri="http://example.com", client_id=CLIENT_ID, client_secret=CLIENT_SECRET, show_dialog=True, cache_path="token.txt" ) )

user_id = sp.current_user()["id"]

song_uris = [] year = date.split("-")[0] for song in music_titles: result = sp.search(q=f"track:{song} year:{year}", type="track") # print(result) # print("space\n\n") try: uri = result["tracks"]["items"][0] song_uris.append(uri) except IndexError: print(f"{song} doesn't exist in Spotify. Skipped.")

Creating a new private playlist in Spotify

playlist = sp.user_playlist_create(user=user_id, name=f"{date} Billboard 100", public=False) print(playlist)

Adding songs found into the new playlist

sp.playlist_add_items(playlist_id=playlist['id'], items=song_uris)

print(playlist['id'])

bro the for loop should be like this:
for song in songs_name[:100]:
song = song.get_text()
result = sp.search(q=f"track:{song} year:{year}", type="track")
print(result)
try:

@navalega0109
Copy link

If anyone needs code for this project then check below code:

import requests
from bs4 import BeautifulSoup
from dotenv import dotenv_values
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from flask import Flask, request, url_for, session, redirect
import time

# Part 2: Spotify Authentication and New Playlist Creation based on Date.
app = Flask(__name__)

secrets = dotenv_values(".env")
app.config['SESSION_COOKIE_NAME'] = secrets['SESSION_COOKIE_NAME']
app.secret_key = secrets['SPOTIFY_APP_SECRET_KEY']
TOKEN_INFO = 'token_info'
SPOTIFY_CLIENT_ID = secrets["SPOTIFY_CLIENT_ID"]
SPOTIFY_CLIENT_SECRET = secrets["SPOTIFY_CLIENT_SECRET"]
BILLBOARD_URL = secrets['BILLBOARD_URL']
date = None

if date is None:
    date = input("Which year do you want to travel to? Type date in this format YYYY-MM-DD : \n\t")

time_travel_url = f"{BILLBOARD_URL}/{date}"

res = requests.get(url=time_travel_url)
res.raise_for_status()
time_travel = res.text

soup = BeautifulSoup(time_travel, "html.parser")

# data_results = soup.find_all(name="h3", id="title-of-a-story")
data_results = soup.select(selector="li ul li h3")
# print(data_results)

song_names = [(song.getText()).strip("\n\t") for song in data_results]
with open(f""
          f"songs_{date}.txt", mode="w") as file:
    for song in song_names:
        file.write(f"{song} \n")

# all the top 100 songs name on given date
# print(song_names)
# data_songs = soup.find_all(name="h3", class_="o-chart-results-list__item")
# print(data_songs)
# songs = [song.getText() for song in data_songs]
# print(songs)


@app.route('/')
def login():
    auth_url = create_spotify_oauth().get_authorize_url()
    return redirect(auth_url)


@app.route('/redirect')
def redirect_page():
    session.clear()
    # get the authCode which needs to be exchanged to get in return auth token
    code = request.args.get('code')
    token_info = create_spotify_oauth().get_access_token(code=code)
    session[TOKEN_INFO] = token_info
    return redirect(url_for('save_to_date', _external=True))


@app.route('/saveToDate')
def save_to_date():
    try:
        token_info = get_token()
    except:
        print('User not logged in.')
        return redirect('/')

    # Use this return to check if our OAuth is successful.
    # return 'OAuth Successful'
    sp = spotipy.Spotify(auth=token_info['access_token'])
    user_id = sp.current_user()['id']
    current_playlists = sp.current_user_playlists()['items']

    song_uris = []
    # Song search to add in playlist
    for song in song_names:
        result = sp.search(q=f"track:{song}", type="track", market="US")
        # print track: find the
        # print(result['tracks']['items'][0])
        try:
            uri = result["tracks"]["items"][0]["uri"]
            song_uris.append(uri)
        except IndexError:
            print(f"{song} doesn't exist in Spotify. Skipped.")
    # print(song_uris)

    # Check if the playlist already exist for given date:
    billboard_100_playlist_id = None
    for playlist in current_playlists:
        if playlist['name'] == f'{date} Billboard 100':
            billboard_100_playlist_id = playlist['id']

    if not billboard_100_playlist_id:
        new_playlist = sp.user_playlist_create(user_id, f'{date} Billboard 100', True)
        billboard_100_playlist_id = new_playlist['id']
        # return f"Billboard top 100 playlist id for date {date} is not found."

    # Now use this playlist to add all the song uris:
    sp.playlist_add_items(billboard_100_playlist_id, song_uris, None)

    print(f"All the songs from timeline {date} added to the playlist '{date} Billboard 100' in spotify.")
    return f"All the songs from timeline {date} added to the playlist '{date} Billboard 100' in spotify."


def get_token():
    token_info = session.get(TOKEN_INFO, None)
    if not token_info:
        redirect(url_for('login', _external=False))

    now = int(time.time())

    is_expired = token_info['expires_at'] - now < 60
    if is_expired:
        spotify_oauth = create_spotify_oauth()
        token_info = spotify_oauth.refresh_access_token(token_info['refresh_token'])

    #  return token info if not expired & if expired then refreshed before sending the given token info.
    return token_info


def create_spotify_oauth():
    return SpotifyOAuth(
        client_id=SPOTIFY_CLIENT_ID,
        client_secret=SPOTIFY_CLIENT_SECRET,
        redirect_uri=url_for('redirect_page', _external=True),
        scope='user-library-read playlist-modify-public playlist-modify-private'
    )


app.run(debug=False)

@AboodALhassan
Copy link

Is anyone else finding this project challenging? I'm having trouble grasping the concepts involved. Any help or clarification would be greatly appreciated

@huzaifasaeed123
Copy link

#Here Is The Complete Project In Simplest Way
from bs4 import BeautifulSoup
import requests
import spotipy
from spotipy.oauth2 import SpotifyOAuth

#date=input("Please Enter date in YYYY-MM- Format")

response=requests.get("https://www.billboard.com/charts/hot-100/2023-08-05/")

soup=BeautifulSoup(response.text,"html.parser")
all_titles= soup.select(selector=".o-chart-results-list__item #title-of-a-story")

client_id="05d82555b91a4325b5e1e5563e4b0faa"
client_secret="5c3d0bc4a04d47b38935ee977742c379"

sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=client_id,
client_secret=client_secret,
redirect_uri='https://example.com',
scope='playlist-modify-private'))

user_profile = sp.current_user()

Extract user ID from the profile

user_id = user_profile['id']
print(user_id)

playlist_name = 'Top 100 Songs'
playlist_description = 'Your Playlist Description'
playlist = sp.user_playlist_create(user=user_id, name=playlist_name, public=False, description=playlist_description)

for titles in all_titles:
print(titles.getText().strip())
# Search for the song
song_title = titles.getText().strip()
search_results = sp.search(q=song_title, type='track')

# Extract the track URI
track_uri = search_results['tracks']['items'][0]['uri']  # Assuming the first search result is the desired song
playlist_id = playlist['id']
sp.playlist_add_items(playlist_id=playlist_id, items=[track_uri])

@Moogeee
Copy link

Moogeee commented Feb 24, 2024

Here is my code, this one is definitely challenging because the documentation is not explained very well (at least for me) so it requires trials and lots of errors. Worked it all out in the end. Hope this helps

from bs4 import BeautifulSoup
import requests
import spotipy
from spotipy.oauth2 import SpotifyOAuth

time_input = input("Enter the time you want to jump to in this format YYYY-MM-DD: ")

URL = "https://www.billboard.com/charts/hot-100/"+time_input

TEMP1 = "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"
TEMP2 = "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"
TEMP3 = "c-label a-no-trucate a-font-primary-s lrv-u-font-size-14@mobile-max u-line-height-normal@mobile-max u-letter-spacing-0021 lrv-u-display-block a-truncate-ellipsis-2line u-max-width-330 u-max-width-230@tablet-only"
TEMP4 = "c-label a-no-trucate a-font-primary-s lrv-u-font-size-14@mobile-max u-line-height-normal@mobile-max u-letter-spacing-0021 lrv-u-display-block a-truncate-ellipsis-2line u-max-width-330 u-max-width-230@tablet-only u-font-size-20@tablet"
# These are classes scrapped from the billboard website

CLIENT_ID = (your client_id here)
CLIENT_SECRET = (your client_secret here)
REDIRECT_URI = "http://example.com"
SPOTIFY_URL = "https://api.spotify.com/v1"
USERNAME = (your username here)

# ------------- SCRAPE BILLBOARD AND GET 2 LISTS OF SONGS AND CORRESPONDING ARTISTS -------------
response = requests.get(URL)
data = response.text
soup = BeautifulSoup(data, "html.parser")
songs = [item.getText().strip() for item in soup.find_all(name="h3", id="title-of-a-story", class_=TEMP1)]
first_song = soup.find(name="h3", id="title-of-a-story", class_=TEMP2).getText().strip()
songs.insert(0, first_song)
artists = [item.getText().strip() for item in soup.find_all(name="span", class_=TEMP3)]
first_artist = soup.find(name="span", class_=TEMP4).getText().strip()
artists.insert(0, first_artist)

# ------------- ACCESS SPOTIFY AND MAKE AUTH -------------
scope = "playlist-modify-private"
sp = spotipy.Spotify(
    auth_manager=SpotifyOAuth(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        redirect_uri=REDIRECT_URI,
        cache_path="token.txt",
        scope=scope,
        show_dialog=True,
        username=USERNAME,
    )
)
user_id = sp.current_user()["id"]

# ------------- CREATE PLAYLIST -------------
playlist = sp.user_playlist_create(
    user=user_id,
    name="Top 100 Billboard songs",
    public=False,
    collaborative=False,
    description=f"Top 100 Billboard songs on {time_input}",
)
playlist_id = playlist["id"]

# ------------- SEARCH FOR SONGS -------------


class NoSongFound(Exception):
    pass


uris = []
for index in range(0, len(songs)):
    try:
        search = sp.search(
            q=f"track:{songs[index]} artist:{artists[index]}",
            limit=1,
            offset=0,
            market=None,
            type="track",
        )
        if search["tracks"]["total"] == 0:
            raise NoSongFound
    except NoSongFound:
        pass
    else:
        uri = str(search["tracks"]["items"][0]["id"])
        uris.append(uri)

# ------------- ADD SONGS -------------
sp.playlist_add_items(playlist_id=playlist_id, items=uris)

print(sp.playlist_items(
    playlist_id=playlist_id,
    additional_types="track",
))

@bluebanana18
Copy link

bluebanana18 commented Feb 28, 2024

Hey guys, I keep getting an insufficient client scope error. What am I still missing in the code?

Also, when I run Angela's code it creates the playlist but can't add any songs. I am a bit lost there lol.

@drakewilcox
Copy link

Hey guys, I keep getting an insufficient client scope error. What am I still missing in the code?

Also, when I run Angela's code it creates the playlist but can't add any songs. I am a bit lost there lol.

@bluebanana18 I was having the exact same issue.

The solution for me was updating the scope in the Spotify Authentication section to include both private and public playlist-modify scopes. (update to line 3 of Angela's code)

Yes, this seems counter intuitive since on line 15 of the example, the created playlist is set as private and has the playlist-modify-private scope set, so you think it would work. But looks like the Spotify API wants both scopes set.

Also you may need to delete your token.txt file before running in order for the token to reset properly.

Example:

sp = spotipy.Spotify(
  auth_manager=SpotifyOAuth(
    scope="playlist-modify-private playlist-modify-public",
    redirect_uri="http://example.com",
    client_id=CLIENT_ID,
    client_secret=CLIENT_SECRET,
    show_dialog=True,
    cache_path="token.txt"
  )
)

Hope this helps

@bluebanana18
Copy link

@drakewilcox
Mind blown. It was really that simple, huh. Thanks a lot!

@grizzleswens
Copy link

Here is my code, it is working perfectly, I had to have a little bit of hand holding from chat gpt

import 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}")

@rickycc
Copy link

rickycc commented Apr 18, 2024

# Use this return to check if our OAuth is successful.
# return 'OAuth Successful'
sp = spotipy.Spotify(auth=token_info['access_token'])
user_id = sp.current_user()['id']
current_playlists = sp.current_user_playlists()['items']

song_uris = []
# Song search to add in playlist
for song in song_names:
    result = sp.search(q=f"track:{song}", type="track", market="US")
    # print track: find the
    # print(result['tracks']['items'][0])
    try:
        uri = result["tracks"]["items"][0]["uri"]
        song_uris.append(uri)
    except IndexError:
        print(f"{song} doesn't exist in Spotify. Skipped.")
# print(song_uris)

# Check if the playlist already exist for given date:
billboard_100_playlist_id = None
for playlist in current_playlists:
    if playlist['name'] == f'{date} Billboard 100':
        billboard_100_playlist_id = playlist['id']

if not billboard_100_playlist_id:
    new_playlist = sp.user_playlist_create(user_id, f'{date} Billboard 100', True)
    billboard_100_playlist_id = new_playlist['id']
    # return f"Billboard top 100 playlist id for date {date} is not found."

Awesome work. However, I am having trouble carrying out the playlist check. I cannot retrieve any information running the line below immediately after the authentication steps. I can print out user_id = sp.current_user()["id"] without any problem.
Can you shed some light on what should i do?

current_playlists = sp.current_user_playlists()['items']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment