CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pylast

A Python interface to Last.fm and Libre.fm for music data, scrobbling, and social features.

Pending
Overview
Eval results
Files

search-discovery.mddocs/

Search and Discovery

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.

Capabilities

Music Search

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."""

Network Search Methods

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
    """

Network Chart Methods

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
    """

Geographic Discovery

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-Based Discovery

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."""

Tag Chart Data

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."""

Image Discovery

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
    """

Data Types for Discovery

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

Constants for Discovery

# 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"

Usage Examples

Artist Search

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

Track and Album Search

# 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():,}")

Geographic Discovery

# 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()}")

Tag-Based Discovery

# 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()}")

Tag Chart Analysis

# 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()}")

Image Discovery

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

Advanced Discovery Workflows

# 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")

Search Result Pagination

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

docs

index.md

music-objects.md

network-auth.md

scrobbling.md

search-discovery.md

user-social.md

tile.json