or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmusic-objects.mdnetwork-auth.mdscrobbling.mdsearch-discovery.mduser-social.md

search-discovery.mddocs/

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

```