Skip to content

Commit

Permalink
Merge pull request #13 from jjoeldaniel/dev
Browse files Browse the repository at this point in the history
Update web scraping and refactor classes
  • Loading branch information
jjoeldaniel authored Dec 29, 2023
2 parents 8e97ce3 + 9a47ad8 commit 7576746
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 36 deletions.
21 changes: 14 additions & 7 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from geniusdotpy.genius_builder import GeniusBuilder
from geniusdotpy.genius import Genius
from geniusdotpy.track import Track


Expand All @@ -7,21 +7,28 @@ def main():
client_access_token = "token"

# Create a GeniusBuilder object
genius = GeniusBuilder(client_access_token=client_access_token)
genius = Genius(client_access_token=client_access_token)

# Search for a track by ID
print(genius.search_track_by_id(378195))
track1 = genius.search_track_by_id(378195)
print(repr(track1))

# Search artist by ID
print(genius.search_artist(16775))
artist1 = genius.search_artist(track1.artist.id)
print(repr(artist1))

# Search for a track by query
print(genius.search("Beat It")[0])
track3 = genius.search("Beat It")[0]
print(repr(track3))

# Search tracks by artist
tracks: list[Track] = genius.search_track_by_artist(artist_id=16775)
print(tracks[0])
print(tracks[0].lyrics)
track4 = tracks[0]
print(repr(track4))

# Retrieve lyrics
track4.get_lyrics()
print(track4.lyrics)


if __name__ == "__main__":
Expand Down
19 changes: 17 additions & 2 deletions geniusdotpy/album.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from geniusdotpy.artist import Artist
import json


class Album:
"""Album class"""

def __init__(self, album_info: dict):
self.album_info = album_info
"""JSON object containing album information."""

self.name: str = album_info["name"]
"""Album name"""
Expand All @@ -26,3 +25,19 @@ def __init__(self, album_info: dict):
self.full_title = album_info["full_title"]
if "artist" in album_info:
self.artist = Artist(album_info["artist"])

self.album_info: dict[str, str] = {
"name": self.name,
"url": self.url,
"full_title": self.full_title,
"artist": self.artist.artist_info,
}
"""JSON object containing album information."""

self.json = json.dumps(self.album_info, indent=2)

def __str__(self):
return f"{self.name} by {self.artist}"

def __repr__(self):
return self.json
18 changes: 15 additions & 3 deletions geniusdotpy/artist.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

class Artist:
"""Genius.com Artist class.
Expand All @@ -15,9 +17,6 @@ def __init__(self, artist_info: dict):
Artist object
"""

self.artist_info = artist_info
"""JSON object containing artist information."""

self.api_path: str = artist_info["api_path"]
"""API path of the artist."""

Expand All @@ -30,5 +29,18 @@ def __init__(self, artist_info: dict):
self.url: str = artist_info["url"]
"""Genius.com URL of the artist."""

self.artist_info: dict[str, str] = {
"api_path": self.api_path,
"id": self.id,
"name": self.name,
"url": self.url,
}
"""Dictionary containing artist information."""

self.json = json.dumps(self.artist_info, indent=2)

def __str__(self):
return self.name

def __repr__(self):
return self.json
14 changes: 6 additions & 8 deletions geniusdotpy/genius_builder.py → geniusdotpy/genius.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
from geniusdotpy.artist import Artist
from geniusdotpy.track import Track
from geniusdotpy.utils import SortType
from geniusdotpy.typing import queryID


class GeniusBuilder:
class Genius:
endpoint = "https://api.genius.com"
"""Genius API endpoint"""

Expand All @@ -21,7 +19,7 @@ def __init__(self, client_access_token: str):

self.headers = {"Authorization": f"Bearer {client_access_token}"}

def search_track_by_id(self, track_id: queryID):
def search_track_by_id(self, track_id: str | int):
"""Search for a track by ID.
Keyword arguments:
Expand All @@ -38,7 +36,7 @@ def search_track_by_id(self, track_id: queryID):

return Track(track_info=response.json()["response"]["song"])

def search_artist(self, artist_id: queryID):
def search_artist(self, artist_id: str | int):
"""Search for an artist by ID.
Keyword arguments:
Expand All @@ -55,7 +53,7 @@ def search_artist(self, artist_id: queryID):

return Artist(artist_info=response.json()["response"]["artist"])

def search(self, query: queryID) -> list[Track]:
def search(self, query: str | int) -> list[Track]:
"""Search for a track by query.
Keyword arguments:
Expand All @@ -78,10 +76,10 @@ def search(self, query: queryID) -> list[Track]:
return tracks

def search_track_by_artist(
self, artist_id: queryID, sort=SortType.TITLE, page=1, per_page=20
self, artist_id: str | int, sort=SortType.TITLE, page=1, per_page=20
) -> list:
endpoint = f"{self.endpoint}/artists/{artist_id}/songs?sort={sort.value}&per_page={per_page}&page={page}"
tracks = list()
tracks: list[Track] = list()

response = requests.get(endpoint, headers=self.headers)
response.raise_for_status()
Expand Down
50 changes: 41 additions & 9 deletions geniusdotpy/track.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from geniusdotpy import utils
from geniusdotpy.album import Album
from geniusdotpy.artist import Artist
import json


class Track:
Expand All @@ -12,7 +13,6 @@ def __init__(self, track_info: dict):
track_info -- JSON object containing track info
"""

self._track_info = track_info
"""JSON object containing track information."""

self.api_path: str = track_info["api_path"]
Expand All @@ -24,7 +24,7 @@ def __init__(self, track_info: dict):
self.url: str = track_info["url"]
"""Genius.com URL of the track."""

self.lyrics: str = utils.retrieve_lyrics(self.url)
self.lyrics: None | str = None
"""Track lyrics."""

self.title: str = track_info["title"]
Expand All @@ -33,7 +33,6 @@ def __init__(self, track_info: dict):
self.artist: Artist = Artist(track_info["primary_artist"])
"""Track artist."""

# Possibly null values
self.release_date: None | datetime.datetime = None
"""Track release date."""

Expand All @@ -59,12 +58,45 @@ def __init__(self, track_info: dict):

if "media" in track_info:
for provider in track_info["media"]:
if provider["provider"] == "youtube":
self.youtube_url = provider["url"]
elif provider["provider"] == "spotify":
self.spotify_url = provider["url"]
elif provider["provider"] == "soundcloud":
self.soundcloud_url = provider["url"]
match provider["provider"]:
case "youtube":
self.youtube_url = provider["url"]
case "spotify":
self.spotify_url = provider["url"]
case "soundcloud":
self.soundcloud_url = provider["url"]


self.track_info: dict = {
"api_path": self.api_path,
"id": self.id,
"url": self.url,
"lyrics": self.lyrics,
"title": self.title,
"artist": self.artist.artist_info,
"release_date": str(self.release_date),
"youtube_url": self.youtube_url,
"spotify_url": self.spotify_url,
"soundcloud_url": self.soundcloud_url,
}

if self.album:
self.track_info["album"] = self.album.album_info
else:
self.track_info["album"] = None

self.json = json.dumps(self.track_info, indent=2)

def get_lyrics(self) -> None | str:
"""Retrieves the lyrics of the track."""

if not self.lyrics:
self.lyrics = utils.retrieve_lyrics(self.url)

return self.lyrics

def __str__(self):
return f"{self.title} by {self.artist.name}"

def __repr__(self):
return self.json
3 changes: 0 additions & 3 deletions geniusdotpy/typing.py

This file was deleted.

9 changes: 5 additions & 4 deletions geniusdotpy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ def retrieve_lyrics(track_url: str):

html = requests.get(track_url).content
soup = BeautifulSoup(html, "html.parser")
res = soup.find("div", class_=lambda x: x and x.startswith("Lyrics__Container"))

res = soup.find("div", class_="Lyrics__Container-sc-1ynbvzw-5")
assert res, "Could not find lyrics (div.Lyrics__Container-sc-1ynbvzw-5))"

return res.get_text(separator="\n")
if res:
return res.get_text(separator="\n")
else:
return None

0 comments on commit 7576746

Please sign in to comment.