Migration Guide: v1.x to v2.0¶
This guide helps you upgrade from SpotifyScraper v1.x to v2.0.
Overview of Changes¶
SpotifyScraper v2.0 is a complete rewrite with a cleaner API, better performance, and more features. While the core functionality remains the same, the API has been significantly improved.
Key Improvements in v2.0¶
- ✅ Simplified API with intuitive method names
- ✅ Better error handling with specific exceptions
- ✅ Type hints throughout for better IDE support
- ✅ Improved performance with connection pooling
- ✅ Built-in media download capabilities
- ✅ Support for Spotify's modern React-based interface
Breaking Changes¶
1. Import Changes¶
v1.x:
from SpotifyScraper.scraper import Scraper, Request
v2.0:
from spotify_scraper import SpotifyClient
2. Client Initialization¶
v1.x:
request = Request().request()
scraper = Scraper(session=request)
v2.0:
client = SpotifyClient()
3. Method Names¶
| v1.x Method | v2.0 Method | Notes |
|---|---|---|
get_track_url_info() |
get_track_info() |
Cleaner name |
get_track_id_info() |
get_track_info() |
Same method handles both |
get_album_url_info() |
get_album_info() |
Cleaner name |
get_album_id_info() |
get_album_info() |
Same method handles both |
get_artist_url_info() |
get_artist_info() |
Cleaner name |
get_playlist_url_info() |
get_playlist_info() |
Cleaner name |
4. Parameter Changes¶
v1.x:
# Separate URL and ID methods
track = scraper.get_track_url_info(url='https://...')
track = scraper.get_track_id_info(track_id='6rqhFgbbKwnb9MLmUQDhG6')
v2.0:
# Single method handles both
track = client.get_track_info('https://...')
track = client.get_track_info('spotify:track:6rqhFgbbKwnb9MLmUQDhG6')
5. Return Value Changes¶
v2.0 returns cleaner, more consistent data structures:
v1.x:
track = {
'track_id': '...',
'track_name': '...',
'track_artists': ['...'],
# Inconsistent naming
}
v2.0:
track = {
'id': '...',
'name': '...',
'artists': [{'id': '...', 'name': '...', 'uri': '...'}],
# Consistent, nested structure
}
Migration Examples¶
Basic Track Extraction¶
v1.x:
from SpotifyScraper.scraper import Scraper, Request
request = Request().request()
scraper = Scraper(session=request)
track = scraper.get_track_url_info(
url='https://open.spotify.com/track/6rqhFgbbKwnb9MLmUQDhG6'
)
print(track['track_name'])
v2.0:
from spotify_scraper import SpotifyClient
client = SpotifyClient()
track = client.get_track_info(
'https://open.spotify.com/track/6rqhFgbbKwnb9MLmUQDhG6'
)
print(track.get('name', 'Unknown'))
Album Extraction with Tracks¶
v1.x:
album = scraper.get_album_url_info(
url='https://open.spotify.com/album/4LH4d3cOWNNsVw41Gqt2kv'
)
# Access nested in 'album_tracks'
for track in album['album_tracks']:
print(track['track_name'])
v2.0:
album = client.get_album_info(
'https://open.spotify.com/album/4LH4d3cOWNNsVw41Gqt2kv'
)
# Cleaner structure
for track in album['tracks']:
print(track.get('name', 'Unknown'))
Error Handling¶
v1.x:
try:
track = scraper.get_track_url_info(url='...')
except Exception as e:
# Generic exception
print(f"Error: {e}")
v2.0:
from spotify_scraper import (
SpotifyClient,
URLError,
NetworkError,
ExtractionError
)
try:
track = client.get_track_info('...')
except URLError:
print("Invalid Spotify URL")
except NetworkError:
print("Network connection failed")
except ExtractionError:
print("Could not extract data")
New Features in v2.0¶
1. Built-in Media Downloads¶
v2.0 includes media download capabilities:
# Download track preview
preview_path = client.download_preview_mp3(track_url, path="previews/")
# Download cover art
cover_path = client.download_cover(album_url, path="covers/")
2. Authentication Support¶
Access lyrics and other authenticated features:
# Use cookie authentication
client = SpotifyClient(cookie_file="spotify_cookies.txt")
# Get track with lyrics
track = client.get_track_info_with_lyrics(track_url)
3. Better Browser Options¶
# Use Selenium for complex scenarios
client = SpotifyClient(browser_type="selenium")
# Use lightweight requests (default)
client = SpotifyClient(browser_type="requests")
4. Type Hints¶
All methods now have proper type hints:
def get_track_info(self, url: str) -> Dict[str, Any]:
"""Extract track information."""
...
Compatibility Layer¶
For easier migration, you can use a compatibility wrapper:
# compatibility.py
from spotify_scraper import SpotifyClient
class Request:
def request(self):
return self
class Scraper:
def __init__(self, session=None):
self.client = SpotifyClient()
def get_track_url_info(self, url):
data = self.client.get_track_info(url)
# Transform to v1 format
return {
'track_id': data['id'],
'track_name': data.get('name', 'Unknown'),
'track_artists': [a['name'] for a in data['artists']],
# ... map other fields
}
def get_album_url_info(self, url):
data = self.client.get_album_info(url)
# Transform to v1 format
return {
'album_id': data['id'],
'album_name': data.get('name', 'Unknown'),
'album_tracks': data['tracks'],
# ... map other fields
}
Step-by-Step Migration¶
1. Update Imports¶
# Find and replace
# OLD: from SpotifyScraper.scraper import Scraper, Request
# NEW: from spotify_scraper import SpotifyClient
2. Update Initialization¶
# Replace request/scraper pattern
# OLD:
# request = Request().request()
# scraper = Scraper(session=request)
# NEW:
client = SpotifyClient()
3. Update Method Calls¶
# Update method names
# OLD: scraper.get_track_url_info(url='...')
# NEW: client.get_track_info('...')
# OLD: scraper.get_track_id_info(track_id='...')
# NEW: client.get_track_info('spotify:track:...')
4. Update Data Access¶
# Update field names
# OLD: track['track_name']
# NEW: track.get('name', 'Unknown')
# OLD: track['track_artists']
# NEW: [a['name'] for a in track['artists']]
5. Add Error Handling¶
# Add specific exception handling
from spotify_scraper import URLError, NetworkError
try:
data = client.get_track_info(url)
except URLError:
# Handle invalid URL
except NetworkError:
# Handle network issues
Common Migration Issues¶
Issue: "No module named 'SpotifyScraper.scraper'"¶
Solution: Update imports to use spotify_scraper (lowercase, underscore)
Issue: "AttributeError: 'Scraper' object has no attribute 'get_track_url_info'"¶
Solution: You're mixing v1 and v2 code. Use SpotifyClient and new method names.
Issue: "KeyError: 'track_name'"¶
Solution: Field names have changed. Use name instead of track_name.
Issue: Different data structure¶
Solution: v2.0 has cleaner, more consistent data structures. Update your code to use the new format.
Testing Your Migration¶
Create a test script to verify your migration:
def test_migration():
"""Test that migration was successful."""
from spotify_scraper import SpotifyClient
client = SpotifyClient()
# Test track extraction
track = client.get_track_info(
"https://open.spotify.com/track/6rqhFgbbKwnb9MLmUQDhG6"
)
assert 'name' in track
assert 'artists' in track
print("✓ Track extraction works")
# Test album extraction
album = client.get_album_info(
"https://open.spotify.com/album/4LH4d3cOWNNsVw41Gqt2kv"
)
assert 'name' in album
assert 'tracks' in album
print("✓ Album extraction works")
print("\nMigration successful! 🎉")
if __name__ == "__main__":
test_migration()
Getting Help¶
If you encounter issues during migration:
- Check this guide for common issues
- Read the API documentation
- Search GitHub issues
- Ask on GitHub Discussions
Why Upgrade?¶
Benefits of v2.0¶
- 🚀 Faster: Improved performance with connection pooling
- 🎯 Cleaner API: Intuitive method names and consistent data
- 🛡️ Better Errors: Specific exceptions for different failures
- 📝 Type Hints: Full IDE support with autocompletion
- 📥 Downloads: Built-in media download capabilities
- 🔧 Maintained: Active development and bug fixes
Long-term Support¶
- v1.x is no longer maintained
- v2.0 is actively developed with regular updates
- Security fixes only applied to v2.0
Summary¶
While v2.0 includes breaking changes, the migration is straightforward:
- Update imports
- Use
SpotifyClientinstead ofScraper - Update method names (remove
_url_infosuffix) - Update field names in returned data
- Add proper error handling
The benefits of cleaner code, better performance, and new features make the upgrade worthwhile!