Add scraping from Spirit FM recently played list, combine with Journey FM and deduplicate songs

This commit is contained in:
nmemmert committed 2025-11-17 11:56:26 -05:00
1 parent 7e7754f533
commit 32d87cf0c2
1 file changed
+78 -67
+78 -67
View File
@@ -31,77 +31,88 @@ SERVER_IP = '172.16.16.106' # Your local server IP
PLAYLIST_NAME = 'Journey FM Recently Played' PLAYLIST_NAME = 'Journey FM Recently Played'
def scrape_recently_played(): def scrape_recently_played():
"""Scrape recently played songs from myjourneyfm.com using Selenium""" """Scrape recently played songs from multiple stations using Selenium"""
options = Options() urls = [
options.add_argument("--headless") 'https://www.myjourneyfm.com/recently-played/',
options.add_argument("--no-sandbox") 'https://spiritfm.com/spiritfm-recently-played/'
options.add_argument("--disable-dev-shm-usage") ]
options.add_argument("--disable-gpu")
options.add_argument("--remote-debugging-port=9222")
options.add_argument("--user-data-dir=/tmp/chromium")
options.add_argument("--no-first-run")
options.add_argument("--disable-extensions")
options.binary_location = "/usr/bin/chromium-browser"
service = Service()
driver = webdriver.Chrome(service=service, options=options)
url = 'https://www.myjourneyfm.com/recently-played/' all_songs = []
driver.get(url) seen = set() # To avoid duplicates
# Wait for initial load for url in urls:
time.sleep(5) options = Options()
options.add_argument("--headless")
# Click "View More" button if exists options.add_argument("--no-sandbox")
try: options.add_argument("--disable-dev-shm-usage")
more_button = driver.find_element(By.ID, "moreSongs") options.add_argument("--disable-gpu")
more_button.click() options.add_argument("--remote-debugging-port=9222")
time.sleep(5) # Wait for more songs to load options.add_argument("--user-data-dir=/tmp/chromium")
except: options.add_argument("--no-first-run")
pass # Button not found or already loaded options.add_argument("--disable-extensions")
options.binary_location = "/usr/bin/chromium-browser"
html = driver.page_source service = Service()
driver.quit() driver = webdriver.Chrome(service=service, options=options)
# Optional: save HTML to file for debugging (comment out if not needed) driver.get(url)
# with open('page.html', 'w', encoding='utf-8') as f:
# f.write(html) # Wait for initial load
time.sleep(5)
soup = BeautifulSoup(html, 'html.parser')
# Click "View More" button if exists
songs = [] try:
# Find elements (div, li) that contain time in their text more_button = driver.find_element(By.ID, "moreSongs")
song_elements = soup.find_all(lambda tag: tag.name in ['div', 'li', 'p'] and re.search(r'\d+:\d+ [AP]M', tag.get_text())) more_button.click()
for element in song_elements: time.sleep(5) # Wait for more songs to load
spans = element.find_all('span') except:
if len(spans) >= 3: pass # Button not found or already loaded
title = spans[0].get_text().strip()
artist = spans[1].get_text().strip() html = driver.page_source
# Ignore time driver.quit()
songs.append({'artist': artist, 'title': title})
else: soup = BeautifulSoup(html, 'html.parser')
# Fallback to text parsing
full_text = element.get_text().strip() songs = []
match = re.search(r'(\d+:\d+ [AP]M)', full_text) # Find elements (div, li) that contain time in their text
if match: song_elements = soup.find_all(lambda tag: tag.name in ['div', 'li', 'p'] and re.search(r'\d+:\d+ [AP]M', tag.get_text()))
play_time = match.group(1) for element in song_elements:
before = full_text.split(play_time)[0].strip() spans = element.find_all('span')
if ' by ' in before: if len(spans) >= 3:
title, artist = before.split(' by ', 1) title = spans[0].get_text().strip()
title = title.strip() artist = spans[1].get_text().strip()
artist = artist.strip() # Ignore time
else: songs.append({'artist': artist, 'title': title})
# Split on capital letters else:
parts = re.findall(r'[A-Z][^A-Z]*', before) # Fallback to text parsing
if len(parts) == 4: full_text = element.get_text().strip()
title = ' '.join(parts[:2]) match = re.search(r'(\d+:\d+ [AP]M)', full_text)
artist = ' '.join(parts[2:]) if match:
play_time = match.group(1)
before = full_text.split(play_time)[0].strip()
if ' by ' in before:
title, artist = before.split(' by ', 1)
title = title.strip()
artist = artist.strip()
else: else:
title = ' '.join(parts[:3]) # Split on capital letters
artist = ' '.join(parts[3:]) parts = re.findall(r'[A-Z][^A-Z]*', before)
if title and artist: if len(parts) == 4:
songs.append({'artist': artist, 'title': title}) title = ' '.join(parts[:2])
artist = ' '.join(parts[2:])
else:
title = ' '.join(parts[:3])
artist = ' '.join(parts[3:])
if title and artist:
songs.append({'artist': artist, 'title': title})
# Add to all_songs, avoiding duplicates
for song in songs:
key = (song['title'].lower(), song['artist'].lower())
if key not in seen:
all_songs.append(song)
seen.add(key)
return songs return all_songs
def normalize_string(s): def normalize_string(s):
"""Normalize string for comparison""" """Normalize string for comparison"""