0
# Search and Discovery
1
2
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.
3
4
## Capabilities
5
6
### Music Search
7
8
Dedicated search classes for discovering music content with pagination support and comprehensive result metadata.
9
10
```python { .api }
11
class ArtistSearch:
12
"""
13
Search for artists by name.
14
15
Args:
16
artist_name (str): Artist name to search for
17
network: Network instance (LastFMNetwork or LibreFMNetwork)
18
"""
19
def __init__(self, artist_name: str, network): ...
20
21
def get_next_page(self) -> list[Artist]:
22
"""
23
Get next page of search results.
24
25
Returns:
26
list[Artist]: List of matching Artist objects
27
"""
28
29
def get_total_result_count(self) -> int:
30
"""
31
Get total number of search results available.
32
33
Returns:
34
int: Total result count across all pages
35
"""
36
37
class TrackSearch:
38
"""
39
Search for tracks by artist and title.
40
41
Args:
42
artist_name (str): Artist name to search for
43
track_name (str): Track name to search for
44
network: Network instance
45
"""
46
def __init__(self, artist_name: str, track_name: str, network): ...
47
48
def get_next_page(self) -> list[Track]:
49
"""Get next page of track search results."""
50
51
def get_total_result_count(self) -> int:
52
"""Get total number of track search results."""
53
54
class AlbumSearch:
55
"""
56
Search for albums by name.
57
58
Args:
59
album_name (str): Album name to search for
60
network: Network instance
61
"""
62
def __init__(self, album_name: str, network): ...
63
64
def get_next_page(self) -> list[Album]:
65
"""Get next page of album search results."""
66
67
def get_total_result_count(self) -> int:
68
"""Get total number of album search results."""
69
```
70
71
### Network Search Methods
72
73
Convenient search methods available directly on network objects for quick searches.
74
75
```python { .api }
76
# Search methods available on LastFMNetwork and LibreFMNetwork
77
78
def search_for_artist(self, artist_name: str) -> ArtistSearch:
79
"""
80
Create an artist search.
81
82
Args:
83
artist_name (str): Artist name to search for
84
85
Returns:
86
ArtistSearch: Artist search object
87
"""
88
89
def search_for_track(self, artist_name: str, track_name: str) -> TrackSearch:
90
"""
91
Create a track search.
92
93
Args:
94
artist_name (str): Artist name
95
track_name (str): Track name
96
97
Returns:
98
TrackSearch: Track search object
99
"""
100
101
def search_for_album(self, album_name: str) -> AlbumSearch:
102
"""
103
Create an album search.
104
105
Args:
106
album_name (str): Album name to search for
107
108
Returns:
109
AlbumSearch: Album search object
110
"""
111
```
112
113
### Network Chart Methods
114
115
Global chart and trending data methods available directly on network objects.
116
117
```python { .api }
118
# Global chart methods available on LastFMNetwork and LibreFMNetwork
119
120
def get_top_artists(self, limit: int = None, cacheable: bool = True) -> list[TopItem]:
121
"""
122
Get global top artists on the network.
123
124
Args:
125
limit (int, optional): Maximum number of results
126
cacheable (bool): Enable caching for this request
127
128
Returns:
129
list[TopItem]: Top artists with play counts
130
"""
131
132
def get_top_tracks(self, limit: int = None, cacheable: bool = True) -> list[TopItem]:
133
"""Get global top tracks on the network."""
134
135
def get_top_tags(self, limit: int = None, cacheable: bool = True) -> list[TopItem]:
136
"""Get global top tags on the network."""
137
138
def get_geo_top_artists(self, country: str, limit: int = None, cacheable: bool = True) -> list[TopItem]:
139
"""
140
Get top artists by country.
141
142
Args:
143
country (str): Country name (ISO 3166-1 format)
144
limit (int, optional): Maximum number of results
145
cacheable (bool): Enable caching
146
147
Returns:
148
list[TopItem]: Top artists in the specified country
149
"""
150
151
def get_geo_top_tracks(self, country: str, location: str = None, limit: int = None, cacheable: bool = True) -> list[TopItem]:
152
"""
153
Get top tracks by country and optional metro area.
154
155
Args:
156
country (str): Country name (ISO 3166-1 format)
157
location (str, optional): Metro area within the country
158
limit (int, optional): Maximum number of results
159
cacheable (bool): Enable caching
160
161
Returns:
162
list[TopItem]: Top tracks in the specified location
163
"""
164
```
165
166
### Geographic Discovery
167
168
Country-based music discovery showing regional music trends and popular content by geographic location.
169
170
```python { .api }
171
class Country:
172
"""
173
Represents a country for geographic music data.
174
175
Args:
176
name (str): Country name
177
network: Network instance
178
"""
179
def __init__(self, name: str, network): ...
180
181
def get_name(self) -> str:
182
"""Get country name."""
183
184
def get_top_artists(self, limit=None, cacheable=True) -> list[TopItem]:
185
"""
186
Get top artists in this country.
187
188
Args:
189
limit (int, optional): Maximum number of results
190
cacheable (bool): Enable caching for this request
191
192
Returns:
193
list[TopItem]: Top artists with popularity weights
194
"""
195
196
def get_top_tracks(self, limit=None, cacheable=True, stream=True) -> list[TopItem]:
197
"""
198
Get top tracks in this country.
199
200
Args:
201
limit (int, optional): Maximum number of results
202
cacheable (bool): Enable caching
203
stream (bool): Stream results for large datasets
204
205
Returns:
206
list[TopItem]: Top tracks with popularity weights
207
"""
208
209
def get_url(self, domain_name=0) -> str:
210
"""
211
Get Last.fm URL for this country's charts.
212
213
Args:
214
domain_name (int): Language domain
215
216
Returns:
217
str: Country's Last.fm URL
218
"""
219
```
220
221
### Tag-Based Discovery
222
223
Tag and genre-based music exploration for discovering content by musical characteristics and user-generated categories.
224
225
```python { .api }
226
class Tag:
227
"""
228
Represents a music tag/genre for content discovery.
229
230
Args:
231
name (str): Tag name
232
network: Network instance
233
"""
234
def __init__(self, name: str, network): ...
235
236
def get_name(self, properly_capitalized=False) -> str:
237
"""
238
Get tag name.
239
240
Args:
241
properly_capitalized (bool): Return properly capitalized name
242
243
Returns:
244
str: Tag name
245
"""
246
247
def get_top_artists(self, limit=None, cacheable=True) -> list[TopItem]:
248
"""
249
Get top artists for this tag.
250
251
Args:
252
limit (int, optional): Maximum number of results
253
cacheable (bool): Enable caching
254
255
Returns:
256
list[TopItem]: Top artists associated with this tag
257
"""
258
259
def get_top_albums(self, limit=None, cacheable=True) -> list[TopItem]:
260
"""Get top albums for this tag."""
261
262
def get_top_tracks(self, limit=None, cacheable=True) -> list[TopItem]:
263
"""Get top tracks for this tag."""
264
265
def get_url(self, domain_name=0) -> str:
266
"""Get Last.fm URL for this tag."""
267
```
268
269
### Tag Chart Data
270
271
Weekly chart functionality for tags to track trending content over time.
272
273
```python { .api }
274
# Weekly chart methods available on Tag objects
275
276
def get_weekly_chart_dates(self) -> list[tuple[str, str]]:
277
"""
278
Get available weekly chart date ranges for this tag.
279
280
Returns:
281
list[tuple[str, str]]: List of (from_date, to_date) tuples
282
"""
283
284
def get_weekly_artist_charts(self, from_date=None, to_date=None) -> list[TopItem]:
285
"""
286
Get weekly artist charts for this tag.
287
288
Args:
289
from_date (str, optional): Start date (YYYY-MM-DD)
290
to_date (str, optional): End date (YYYY-MM-DD)
291
292
Returns:
293
list[TopItem]: Weekly top artists for this tag
294
"""
295
296
def get_weekly_album_charts(self, from_date=None, to_date=None) -> list[TopItem]:
297
"""Get weekly album charts for this tag."""
298
299
def get_weekly_track_charts(self, from_date=None, to_date=None) -> list[TopItem]:
300
"""Get weekly track charts for this tag."""
301
```
302
303
### Image Discovery
304
305
Music-related image discovery and browsing capabilities.
306
307
```python { .api }
308
# Image discovery methods available on music objects
309
310
def get_images(self, order="popularity", limit=None) -> list[Image]:
311
"""
312
Get images related to music objects.
313
314
Args:
315
order (str): Sort order ("popularity" or "dateadded")
316
limit (int, optional): Maximum number of images
317
318
Returns:
319
list[Image]: Related images with metadata
320
"""
321
```
322
323
## Data Types for Discovery
324
325
```python { .api }
326
from collections import namedtuple
327
328
Image = namedtuple('Image', ['title', 'url', 'dateadded', 'format', 'owner', 'sizes', 'votes'])
329
"""
330
Represents an image with metadata.
331
332
Fields:
333
title (str): Image title
334
url (str): Primary image URL
335
dateadded (str): Date image was added
336
format (str): Image format (jpg, png, etc.)
337
owner (str): Username of image owner
338
sizes (ImageSizes): Different size URLs
339
votes (int): User votes for this image
340
"""
341
342
ImageSizes = namedtuple('ImageSizes', ['original', 'large', 'largesquare', 'medium', 'small', 'extralarge'])
343
"""
344
Different sizes of an image.
345
346
Fields:
347
original (str): Original size URL
348
large (str): Large size URL
349
largesquare (str): Large square crop URL
350
medium (str): Medium size URL
351
small (str): Small size URL
352
extralarge (str): Extra large size URL
353
"""
354
355
TopItem = namedtuple('TopItem', ['item', 'weight'])
356
"""
357
Represents a top item with weight/ranking.
358
359
Fields:
360
item (Artist/Album/Track/Tag): The ranked item
361
weight (int): Ranking weight (higher = more popular)
362
"""
363
```
364
365
## Constants for Discovery
366
367
```python { .api }
368
# Image ordering options
369
IMAGES_ORDER_POPULARITY = "popularity"
370
IMAGES_ORDER_DATE = "dateadded"
371
372
# Image size constants
373
SIZE_SMALL = 0
374
SIZE_MEDIUM = 1
375
SIZE_LARGE = 2
376
SIZE_EXTRA_LARGE = 3
377
SIZE_MEGA = 4
378
379
# Time periods for charts
380
PERIOD_OVERALL = "overall"
381
PERIOD_7DAYS = "7day"
382
PERIOD_1MONTH = "1month"
383
PERIOD_3MONTHS = "3month"
384
PERIOD_6MONTHS = "6month"
385
PERIOD_12MONTHS = "12month"
386
```
387
388
## Usage Examples
389
390
### Artist Search
391
392
```python
393
import pylast
394
395
network = pylast.LastFMNetwork(api_key=API_KEY, api_secret=API_SECRET)
396
397
# Search for artists
398
search = network.search_for_artist("radiohead")
399
print(f"Total results: {search.get_total_result_count()}")
400
401
# Get first page of results
402
artists = search.get_next_page()
403
print("Search Results:")
404
for i, artist in enumerate(artists, 1):
405
print(f"{i:2d}. {artist.get_name()}")
406
print(f" Listeners: {artist.get_listener_count():,}")
407
print(f" Play count: {artist.get_playcount():,}")
408
409
# Get more results if available
410
if search.get_total_result_count() > len(artists):
411
more_artists = search.get_next_page()
412
print(f"\nNext {len(more_artists)} results:")
413
for artist in more_artists:
414
print(f"- {artist.get_name()}")
415
```
416
417
### Track and Album Search
418
419
```python
420
# Search for tracks
421
track_search = network.search_for_track("pink floyd", "time")
422
tracks = track_search.get_next_page()
423
424
print("Track Search Results:")
425
for track in tracks[:10]: # Limit to first 10
426
album = track.get_album()
427
duration = track.get_duration()
428
duration_str = f"{duration // 60000}:{(duration % 60000) // 1000:02d}" if duration else "Unknown"
429
430
print(f"- {track.get_artist().get_name()} - {track.get_title()}")
431
if album:
432
print(f" Album: {album.get_title()}")
433
print(f" Duration: {duration_str}")
434
435
# Search for albums
436
album_search = network.search_for_album("dark side of the moon")
437
albums = album_search.get_next_page()
438
439
print("\nAlbum Search Results:")
440
for album in albums[:5]:
441
print(f"- {album.get_artist().get_name()} - {album.get_title()}")
442
print(f" Listeners: {album.get_listener_count():,}")
443
```
444
445
### Geographic Discovery
446
447
```python
448
# Explore music by country
449
countries = ["United States", "United Kingdom", "Japan", "Brazil", "Germany"]
450
451
for country_name in countries:
452
country = network.get_country(country_name)
453
top_artists = country.get_top_artists(limit=5)
454
455
print(f"\nTop Artists in {country.get_name()}:")
456
for i, artist_item in enumerate(top_artists, 1):
457
artist = artist_item.item
458
popularity = artist_item.weight
459
print(f"{i}. {artist.get_name()} (popularity: {popularity})")
460
461
# Get top tracks by country
462
uk = network.get_country("United Kingdom")
463
uk_tracks = uk.get_top_tracks(limit=10)
464
465
print("\nTop Tracks in UK:")
466
for track_item in uk_tracks:
467
track = track_item.item
468
print(f"- {track.get_artist().get_name()} - {track.get_title()}")
469
```
470
471
### Tag-Based Discovery
472
473
```python
474
# Explore music by genre/tag
475
genres = ["rock", "electronic", "jazz", "hip hop", "indie"]
476
477
for genre_name in genres:
478
tag = network.get_tag(genre_name)
479
top_artists = tag.get_top_artists(limit=5)
480
481
print(f"\nTop {tag.get_name(properly_capitalized=True)} Artists:")
482
for artist_item in top_artists:
483
artist = artist_item.item
484
print(f"- {artist.get_name()}")
485
486
# Get albums and tracks for a specific tag
487
rock_tag = network.get_tag("rock")
488
489
rock_albums = rock_tag.get_top_albums(limit=5)
490
print("\nTop Rock Albums:")
491
for album_item in rock_albums:
492
album = album_item.item
493
print(f"- {album.get_artist().get_name()} - {album.get_title()}")
494
495
rock_tracks = rock_tag.get_top_tracks(limit=5)
496
print("\nTop Rock Tracks:")
497
for track_item in rock_tracks:
498
track = track_item.item
499
print(f"- {track.get_artist().get_name()} - {track.get_title()}")
500
```
501
502
### Tag Chart Analysis
503
504
```python
505
# Analyze trending music for a tag
506
electronic_tag = network.get_tag("electronic")
507
508
# Get available chart periods
509
chart_dates = electronic_tag.get_weekly_chart_dates()
510
if chart_dates:
511
# Get latest weekly chart
512
latest_from, latest_to = chart_dates[-1]
513
weekly_artists = electronic_tag.get_weekly_artist_charts(latest_from, latest_to)
514
515
print(f"Trending Electronic Artists ({latest_from} to {latest_to}):")
516
for i, artist_item in enumerate(weekly_artists[:10], 1):
517
artist = artist_item.item
518
plays = artist_item.weight
519
print(f"{i:2d}. {artist.get_name()} ({plays} plays)")
520
521
# Get weekly tracks
522
weekly_tracks = electronic_tag.get_weekly_track_charts(latest_from, latest_to)
523
print(f"\nTrending Electronic Tracks:")
524
for track_item in weekly_tracks[:5]:
525
track = track_item.item
526
print(f"- {track.get_artist().get_name()} - {track.get_title()}")
527
```
528
529
### Image Discovery
530
531
```python
532
# Find images for artists
533
artist = network.get_artist("The Beatles")
534
images = artist.get_images(order="popularity", limit=10)
535
536
print(f"Images for {artist.get_name()}:")
537
for i, image in enumerate(images, 1):
538
print(f"{i:2d}. {image.title}")
539
print(f" URL: {image.url}")
540
print(f" Format: {image.format}")
541
print(f" Owner: {image.owner}")
542
print(f" Votes: {image.votes}")
543
print(f" Added: {image.dateadded}")
544
545
# Access different sizes
546
sizes = image.sizes
547
if sizes.large:
548
print(f" Large: {sizes.large}")
549
if sizes.medium:
550
print(f" Medium: {sizes.medium}")
551
552
# Get images ordered by date
553
recent_images = artist.get_images(order="dateadded", limit=5)
554
print(f"\nRecent images for {artist.get_name()}:")
555
for image in recent_images:
556
print(f"- {image.title} (added {image.dateadded})")
557
```
558
559
### Advanced Discovery Workflows
560
561
```python
562
# Discover new music through tag exploration
563
def discover_similar_tags(base_tag_name, depth=2):
564
"""Discover related tags and their top content"""
565
tag = network.get_tag(base_tag_name)
566
567
# Get top artists for this tag
568
top_artists = tag.get_top_artists(limit=10)
569
570
# Find tags from top artists
571
related_tags = set()
572
for artist_item in top_artists[:5]: # Sample top 5 artists
573
artist = artist_item.item
574
artist_tags = artist.get_top_tags(limit=5)
575
for tag_item in artist_tags:
576
related_tag_name = tag_item.item.get_name().lower()
577
if related_tag_name != base_tag_name.lower():
578
related_tags.add(related_tag_name)
579
580
print(f"Tags related to '{base_tag_name}':")
581
for related_tag in list(related_tags)[:depth]:
582
print(f"- {related_tag}")
583
584
# Get top artist for related tag
585
rel_tag_obj = network.get_tag(related_tag)
586
rel_artists = rel_tag_obj.get_top_artists(limit=3)
587
for artist_item in rel_artists:
588
print(f" • {artist_item.item.get_name()}")
589
590
# Discover new music
591
discover_similar_tags("shoegaze")
592
593
# Geographic music exploration
594
def explore_country_genres(country_name):
595
"""Explore popular genres in a specific country"""
596
country = network.get_country(country_name)
597
top_artists = country.get_top_artists(limit=20)
598
599
# Collect tags from top artists
600
country_tags = {}
601
for artist_item in top_artists:
602
artist = artist_item.item
603
artist_tags = artist.get_top_tags(limit=3)
604
for tag_item in artist_tags:
605
tag_name = tag_item.item.get_name()
606
weight = tag_item.weight
607
if tag_name in country_tags:
608
country_tags[tag_name] += weight
609
else:
610
country_tags[tag_name] = weight
611
612
# Sort by popularity
613
sorted_tags = sorted(country_tags.items(), key=lambda x: x[1], reverse=True)
614
615
print(f"Popular genres in {country_name}:")
616
for tag_name, weight in sorted_tags[:10]:
617
print(f"- {tag_name} (weight: {weight})")
618
619
explore_country_genres("Japan")
620
```
621
622
### Search Result Pagination
623
624
```python
625
def paginate_search_results(search_obj, page_size=10, max_pages=5):
626
"""Helper function to paginate through search results"""
627
total_results = search_obj.get_total_result_count()
628
print(f"Total results: {total_results}")
629
630
page = 1
631
all_results = []
632
633
while page <= max_pages:
634
try:
635
results = search_obj.get_next_page()
636
if not results: # No more results
637
break
638
639
print(f"\nPage {page}:")
640
for i, item in enumerate(results[:page_size], 1):
641
if hasattr(item, 'get_name'):
642
print(f"{i:2d}. {item.get_name()}")
643
elif hasattr(item, 'get_title'):
644
artist_name = item.get_artist().get_name() if hasattr(item, 'get_artist') else "Unknown"
645
print(f"{i:2d}. {artist_name} - {item.get_title()}")
646
647
all_results.extend(results[:page_size])
648
page += 1
649
650
except Exception as e:
651
print(f"Error getting page {page}: {e}")
652
break
653
654
return all_results
655
656
# Use pagination helper
657
artist_search = network.search_for_artist("smith")
658
paginate_search_results(artist_search, page_size=5, max_pages=3)
659
```