A Python interface to Last.fm and Libre.fm for music data, scrobbling, and social features.
—
Music search capabilities, content discovery, geographic data, and tag-based music exploration. This covers PyLast's comprehensive search functionality, content discovery mechanisms, and geographic/categorical music data access.
Dedicated search classes for discovering music content with pagination support and comprehensive result metadata.
class ArtistSearch:
"""
Search for artists by name.
Args:
artist_name (str): Artist name to search for
network: Network instance (LastFMNetwork or LibreFMNetwork)
"""
def __init__(self, artist_name: str, network): ...
def get_next_page(self) -> list[Artist]:
"""
Get next page of search results.
Returns:
list[Artist]: List of matching Artist objects
"""
def get_total_result_count(self) -> int:
"""
Get total number of search results available.
Returns:
int: Total result count across all pages
"""
class TrackSearch:
"""
Search for tracks by artist and title.
Args:
artist_name (str): Artist name to search for
track_name (str): Track name to search for
network: Network instance
"""
def __init__(self, artist_name: str, track_name: str, network): ...
def get_next_page(self) -> list[Track]:
"""Get next page of track search results."""
def get_total_result_count(self) -> int:
"""Get total number of track search results."""
class AlbumSearch:
"""
Search for albums by name.
Args:
album_name (str): Album name to search for
network: Network instance
"""
def __init__(self, album_name: str, network): ...
def get_next_page(self) -> list[Album]:
"""Get next page of album search results."""
def get_total_result_count(self) -> int:
"""Get total number of album search results."""Convenient search methods available directly on network objects for quick searches.
# Search methods available on LastFMNetwork and LibreFMNetwork
def search_for_artist(self, artist_name: str) -> ArtistSearch:
"""
Create an artist search.
Args:
artist_name (str): Artist name to search for
Returns:
ArtistSearch: Artist search object
"""
def search_for_track(self, artist_name: str, track_name: str) -> TrackSearch:
"""
Create a track search.
Args:
artist_name (str): Artist name
track_name (str): Track name
Returns:
TrackSearch: Track search object
"""
def search_for_album(self, album_name: str) -> AlbumSearch:
"""
Create an album search.
Args:
album_name (str): Album name to search for
Returns:
AlbumSearch: Album search object
"""Global chart and trending data methods available directly on network objects.
# Global chart methods available on LastFMNetwork and LibreFMNetwork
def get_top_artists(self, limit: int = None, cacheable: bool = True) -> list[TopItem]:
"""
Get global top artists on the network.
Args:
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching for this request
Returns:
list[TopItem]: Top artists with play counts
"""
def get_top_tracks(self, limit: int = None, cacheable: bool = True) -> list[TopItem]:
"""Get global top tracks on the network."""
def get_top_tags(self, limit: int = None, cacheable: bool = True) -> list[TopItem]:
"""Get global top tags on the network."""
def get_geo_top_artists(self, country: str, limit: int = None, cacheable: bool = True) -> list[TopItem]:
"""
Get top artists by country.
Args:
country (str): Country name (ISO 3166-1 format)
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching
Returns:
list[TopItem]: Top artists in the specified country
"""
def get_geo_top_tracks(self, country: str, location: str = None, limit: int = None, cacheable: bool = True) -> list[TopItem]:
"""
Get top tracks by country and optional metro area.
Args:
country (str): Country name (ISO 3166-1 format)
location (str, optional): Metro area within the country
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching
Returns:
list[TopItem]: Top tracks in the specified location
"""Country-based music discovery showing regional music trends and popular content by geographic location.
class Country:
"""
Represents a country for geographic music data.
Args:
name (str): Country name
network: Network instance
"""
def __init__(self, name: str, network): ...
def get_name(self) -> str:
"""Get country name."""
def get_top_artists(self, limit=None, cacheable=True) -> list[TopItem]:
"""
Get top artists in this country.
Args:
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching for this request
Returns:
list[TopItem]: Top artists with popularity weights
"""
def get_top_tracks(self, limit=None, cacheable=True, stream=True) -> list[TopItem]:
"""
Get top tracks in this country.
Args:
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching
stream (bool): Stream results for large datasets
Returns:
list[TopItem]: Top tracks with popularity weights
"""
def get_url(self, domain_name=0) -> str:
"""
Get Last.fm URL for this country's charts.
Args:
domain_name (int): Language domain
Returns:
str: Country's Last.fm URL
"""Tag and genre-based music exploration for discovering content by musical characteristics and user-generated categories.
class Tag:
"""
Represents a music tag/genre for content discovery.
Args:
name (str): Tag name
network: Network instance
"""
def __init__(self, name: str, network): ...
def get_name(self, properly_capitalized=False) -> str:
"""
Get tag name.
Args:
properly_capitalized (bool): Return properly capitalized name
Returns:
str: Tag name
"""
def get_top_artists(self, limit=None, cacheable=True) -> list[TopItem]:
"""
Get top artists for this tag.
Args:
limit (int, optional): Maximum number of results
cacheable (bool): Enable caching
Returns:
list[TopItem]: Top artists associated with this tag
"""
def get_top_albums(self, limit=None, cacheable=True) -> list[TopItem]:
"""Get top albums for this tag."""
def get_top_tracks(self, limit=None, cacheable=True) -> list[TopItem]:
"""Get top tracks for this tag."""
def get_url(self, domain_name=0) -> str:
"""Get Last.fm URL for this tag."""Weekly chart functionality for tags to track trending content over time.
# Weekly chart methods available on Tag objects
def get_weekly_chart_dates(self) -> list[tuple[str, str]]:
"""
Get available weekly chart date ranges for this tag.
Returns:
list[tuple[str, str]]: List of (from_date, to_date) tuples
"""
def get_weekly_artist_charts(self, from_date=None, to_date=None) -> list[TopItem]:
"""
Get weekly artist charts for this tag.
Args:
from_date (str, optional): Start date (YYYY-MM-DD)
to_date (str, optional): End date (YYYY-MM-DD)
Returns:
list[TopItem]: Weekly top artists for this tag
"""
def get_weekly_album_charts(self, from_date=None, to_date=None) -> list[TopItem]:
"""Get weekly album charts for this tag."""
def get_weekly_track_charts(self, from_date=None, to_date=None) -> list[TopItem]:
"""Get weekly track charts for this tag."""Music-related image discovery and browsing capabilities.
# Image discovery methods available on music objects
def get_images(self, order="popularity", limit=None) -> list[Image]:
"""
Get images related to music objects.
Args:
order (str): Sort order ("popularity" or "dateadded")
limit (int, optional): Maximum number of images
Returns:
list[Image]: Related images with metadata
"""from collections import namedtuple
Image = namedtuple('Image', ['title', 'url', 'dateadded', 'format', 'owner', 'sizes', 'votes'])
"""
Represents an image with metadata.
Fields:
title (str): Image title
url (str): Primary image URL
dateadded (str): Date image was added
format (str): Image format (jpg, png, etc.)
owner (str): Username of image owner
sizes (ImageSizes): Different size URLs
votes (int): User votes for this image
"""
ImageSizes = namedtuple('ImageSizes', ['original', 'large', 'largesquare', 'medium', 'small', 'extralarge'])
"""
Different sizes of an image.
Fields:
original (str): Original size URL
large (str): Large size URL
largesquare (str): Large square crop URL
medium (str): Medium size URL
small (str): Small size URL
extralarge (str): Extra large size URL
"""
TopItem = namedtuple('TopItem', ['item', 'weight'])
"""
Represents a top item with weight/ranking.
Fields:
item (Artist/Album/Track/Tag): The ranked item
weight (int): Ranking weight (higher = more popular)
"""# Image ordering options
IMAGES_ORDER_POPULARITY = "popularity"
IMAGES_ORDER_DATE = "dateadded"
# Image size constants
SIZE_SMALL = 0
SIZE_MEDIUM = 1
SIZE_LARGE = 2
SIZE_EXTRA_LARGE = 3
SIZE_MEGA = 4
# Time periods for charts
PERIOD_OVERALL = "overall"
PERIOD_7DAYS = "7day"
PERIOD_1MONTH = "1month"
PERIOD_3MONTHS = "3month"
PERIOD_6MONTHS = "6month"
PERIOD_12MONTHS = "12month"import pylast
network = pylast.LastFMNetwork(api_key=API_KEY, api_secret=API_SECRET)
# Search for artists
search = network.search_for_artist("radiohead")
print(f"Total results: {search.get_total_result_count()}")
# Get first page of results
artists = search.get_next_page()
print("Search Results:")
for i, artist in enumerate(artists, 1):
print(f"{i:2d}. {artist.get_name()}")
print(f" Listeners: {artist.get_listener_count():,}")
print(f" Play count: {artist.get_playcount():,}")
# Get more results if available
if search.get_total_result_count() > len(artists):
more_artists = search.get_next_page()
print(f"\nNext {len(more_artists)} results:")
for artist in more_artists:
print(f"- {artist.get_name()}")# Search for tracks
track_search = network.search_for_track("pink floyd", "time")
tracks = track_search.get_next_page()
print("Track Search Results:")
for track in tracks[:10]: # Limit to first 10
album = track.get_album()
duration = track.get_duration()
duration_str = f"{duration // 60000}:{(duration % 60000) // 1000:02d}" if duration else "Unknown"
print(f"- {track.get_artist().get_name()} - {track.get_title()}")
if album:
print(f" Album: {album.get_title()}")
print(f" Duration: {duration_str}")
# Search for albums
album_search = network.search_for_album("dark side of the moon")
albums = album_search.get_next_page()
print("\nAlbum Search Results:")
for album in albums[:5]:
print(f"- {album.get_artist().get_name()} - {album.get_title()}")
print(f" Listeners: {album.get_listener_count():,}")# Explore music by country
countries = ["United States", "United Kingdom", "Japan", "Brazil", "Germany"]
for country_name in countries:
country = network.get_country(country_name)
top_artists = country.get_top_artists(limit=5)
print(f"\nTop Artists in {country.get_name()}:")
for i, artist_item in enumerate(top_artists, 1):
artist = artist_item.item
popularity = artist_item.weight
print(f"{i}. {artist.get_name()} (popularity: {popularity})")
# Get top tracks by country
uk = network.get_country("United Kingdom")
uk_tracks = uk.get_top_tracks(limit=10)
print("\nTop Tracks in UK:")
for track_item in uk_tracks:
track = track_item.item
print(f"- {track.get_artist().get_name()} - {track.get_title()}")# Explore music by genre/tag
genres = ["rock", "electronic", "jazz", "hip hop", "indie"]
for genre_name in genres:
tag = network.get_tag(genre_name)
top_artists = tag.get_top_artists(limit=5)
print(f"\nTop {tag.get_name(properly_capitalized=True)} Artists:")
for artist_item in top_artists:
artist = artist_item.item
print(f"- {artist.get_name()}")
# Get albums and tracks for a specific tag
rock_tag = network.get_tag("rock")
rock_albums = rock_tag.get_top_albums(limit=5)
print("\nTop Rock Albums:")
for album_item in rock_albums:
album = album_item.item
print(f"- {album.get_artist().get_name()} - {album.get_title()}")
rock_tracks = rock_tag.get_top_tracks(limit=5)
print("\nTop Rock Tracks:")
for track_item in rock_tracks:
track = track_item.item
print(f"- {track.get_artist().get_name()} - {track.get_title()}")# Analyze trending music for a tag
electronic_tag = network.get_tag("electronic")
# Get available chart periods
chart_dates = electronic_tag.get_weekly_chart_dates()
if chart_dates:
# Get latest weekly chart
latest_from, latest_to = chart_dates[-1]
weekly_artists = electronic_tag.get_weekly_artist_charts(latest_from, latest_to)
print(f"Trending Electronic Artists ({latest_from} to {latest_to}):")
for i, artist_item in enumerate(weekly_artists[:10], 1):
artist = artist_item.item
plays = artist_item.weight
print(f"{i:2d}. {artist.get_name()} ({plays} plays)")
# Get weekly tracks
weekly_tracks = electronic_tag.get_weekly_track_charts(latest_from, latest_to)
print(f"\nTrending Electronic Tracks:")
for track_item in weekly_tracks[:5]:
track = track_item.item
print(f"- {track.get_artist().get_name()} - {track.get_title()}")# Find images for artists
artist = network.get_artist("The Beatles")
images = artist.get_images(order="popularity", limit=10)
print(f"Images for {artist.get_name()}:")
for i, image in enumerate(images, 1):
print(f"{i:2d}. {image.title}")
print(f" URL: {image.url}")
print(f" Format: {image.format}")
print(f" Owner: {image.owner}")
print(f" Votes: {image.votes}")
print(f" Added: {image.dateadded}")
# Access different sizes
sizes = image.sizes
if sizes.large:
print(f" Large: {sizes.large}")
if sizes.medium:
print(f" Medium: {sizes.medium}")
# Get images ordered by date
recent_images = artist.get_images(order="dateadded", limit=5)
print(f"\nRecent images for {artist.get_name()}:")
for image in recent_images:
print(f"- {image.title} (added {image.dateadded})")# Discover new music through tag exploration
def discover_similar_tags(base_tag_name, depth=2):
"""Discover related tags and their top content"""
tag = network.get_tag(base_tag_name)
# Get top artists for this tag
top_artists = tag.get_top_artists(limit=10)
# Find tags from top artists
related_tags = set()
for artist_item in top_artists[:5]: # Sample top 5 artists
artist = artist_item.item
artist_tags = artist.get_top_tags(limit=5)
for tag_item in artist_tags:
related_tag_name = tag_item.item.get_name().lower()
if related_tag_name != base_tag_name.lower():
related_tags.add(related_tag_name)
print(f"Tags related to '{base_tag_name}':")
for related_tag in list(related_tags)[:depth]:
print(f"- {related_tag}")
# Get top artist for related tag
rel_tag_obj = network.get_tag(related_tag)
rel_artists = rel_tag_obj.get_top_artists(limit=3)
for artist_item in rel_artists:
print(f" • {artist_item.item.get_name()}")
# Discover new music
discover_similar_tags("shoegaze")
# Geographic music exploration
def explore_country_genres(country_name):
"""Explore popular genres in a specific country"""
country = network.get_country(country_name)
top_artists = country.get_top_artists(limit=20)
# Collect tags from top artists
country_tags = {}
for artist_item in top_artists:
artist = artist_item.item
artist_tags = artist.get_top_tags(limit=3)
for tag_item in artist_tags:
tag_name = tag_item.item.get_name()
weight = tag_item.weight
if tag_name in country_tags:
country_tags[tag_name] += weight
else:
country_tags[tag_name] = weight
# Sort by popularity
sorted_tags = sorted(country_tags.items(), key=lambda x: x[1], reverse=True)
print(f"Popular genres in {country_name}:")
for tag_name, weight in sorted_tags[:10]:
print(f"- {tag_name} (weight: {weight})")
explore_country_genres("Japan")def paginate_search_results(search_obj, page_size=10, max_pages=5):
"""Helper function to paginate through search results"""
total_results = search_obj.get_total_result_count()
print(f"Total results: {total_results}")
page = 1
all_results = []
while page <= max_pages:
try:
results = search_obj.get_next_page()
if not results: # No more results
break
print(f"\nPage {page}:")
for i, item in enumerate(results[:page_size], 1):
if hasattr(item, 'get_name'):
print(f"{i:2d}. {item.get_name()}")
elif hasattr(item, 'get_title'):
artist_name = item.get_artist().get_name() if hasattr(item, 'get_artist') else "Unknown"
print(f"{i:2d}. {artist_name} - {item.get_title()}")
all_results.extend(results[:page_size])
page += 1
except Exception as e:
print(f"Error getting page {page}: {e}")
break
return all_results
# Use pagination helper
artist_search = network.search_for_artist("smith")
paginate_search_results(artist_search, page_size=5, max_pages=3)Install with Tessl CLI
npx tessl i tessl/pypi-pylast