Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ bands[0].name
# Fetch band page
band = bands[0].get()

# Fetch band's similiar artists
band.similar_artists
# -> <SimilarArtists: Megadeth (490) | Testament (415) | Exodus (212) | Evile (206) | Anthrax (184) | Death Angel (149) | Diamond Head (119) | Xentrix (114) | Annihilator (110) | Newsted (108) | Heathen (106) | Metal Church (105) | Flotsam and Jetsam (103) | Slayer (71) | Trivium (70) | Overkill (66) | Artillery (58) | Mortal Sin (58) | Volbeat (55) | Sacred Reich (50)>

# Get all albums
band.albums
# -> [<Album: No Life 'til Leather (Demo)>, <Album: Kill 'Em All (Full-length)>, ...]
Expand Down
94 changes: 92 additions & 2 deletions metallum.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
import requests_cache
from dateutil import parser as date_parser
from pyquery import PyQuery
from requests_cache.core import remove_expired_responses
#from requests_cache.core import remove_expired_responses

CACHE_FILE = os.path.join(tempfile.gettempdir(), 'metallum_cache')
requests_cache.install_cache(cache_name=CACHE_FILE, expire_after=300)
remove_expired_responses()
#remove_expired_responses()

# Site details
BASE_URL = 'https://www.metal-archives.com'
Expand Down Expand Up @@ -534,6 +534,95 @@ def albums(self) -> List['AlbumCollection']:
url = 'band/discography/id/{0}/tab/all'.format(self.id)
return AlbumCollection(url)

@property
def similar_artists(self):
"""
>>> band.similar_artists
<SimilarArtists: Megadeth (488) | Testament (420) | Exodus (212) | Evile (206) | Anthrax (182) | Death Angel (148) | Diamond Head (119) | Xentrix (115) | Annihilator (111) | Newsted (108) | Metal Church (105) | Heathen (105) | Flotsam and Jetsam (104) | Slayer (71) | Trivium (70) | Overkill (66) | Artillery (58) | Mortal Sin (58) | Volbeat (55) | Sacred Reich (48) | Paradox (44) | Slammer (34) | Pantera (33) | Corrosion of Conformity (30) | Am I Blood (30) | Alice in Chains (25) | Stone (25) | Motörhead (21) | Dark Angel (20) | Vio-lence (20) | Meliah Rage (19) | Machine Head (18) | Onslaught (18) | Tantara (18) | Kreator (17) | Outrage (17) | Blitzkrieg (16) | Znöwhite (16) | Forbidden (15) | Suicidal Tendencies (15) | Cyclone Temple (15) | Whiplash (15) | Havok (14) | Defiance (14) | Accu§er (13) | Deliverance (13) | Lȧȧz Rockit (13) | Reign of Fury (13) | Woslom (13) | Kat (12) | Iced Earth (12) | 4Arm (12) | Acrassicauda (11) | Wrathchild America (11) | Sepultura (11) | Power Trip (11) | Apocalypse (11) | Ellefson (11) | Metal Allegiance (11) | Alcoholica (11) | Wildhunt (11) | Mercyful Fate (10) | Железный Поток (10) | Destruction (10) | Sufosia (10) | Nuclear Assault (9) | Tourniquet (9) | Shah (9) | Faith No More (8) | Channel Zero (8) | Mantic Ritual (8) | Dust Bolt (8) | Hammerhedd (8) | Eradikator (8) | Ramp (8) | Earthquake (8) | Anesthesia (8) | Inciter (8) | Hirax (7) | Shadows Fall (7) | Faith or Fear (7) | Game Over (7) | Holocaust (7) | Sweet Savage (7) | Blackened (7) | Morgana Lefay (7) | Hellraiser (7) | Razor (7) | Posehn (7) | Eternal Decision (6) | Armored Saint (6) | Austrian Death Machine (6) | Hatriot (6) | Vindicator (6) | Dublin Death Patrol (6) | Sylosis (6) | Angelus Apatrida (6) | Addictive (6) | Hunter (6) | Meshiaak (6) | Vader (6) | Living Sacrifice (6) | Thrashback (6) | Venom Inc. (6) | Athena (6) | Prong (5) | Danzig (5) | Thrashsteel (5) | Fallen Angel (5) | Lost Society (5) | Ekhymosis (5) | Attomica (5) | Raven (5) | In.Si.Dia (5) | Turbo (5) | Act of Defiance (5) | Hellripper (5) | Suicidal Angels (5) | Phantom Lord (5) | Sanctity (5) | Wargasm (5) | Seducer (5) | Calipash (5) | Detritus (5) | Enforcer (5) | Mason (5) | Tyrant's Reign (5) | Braindamage (5) | Vortex (5) | Abandoned (5) | Arbitrater (5) | Bleak House (5) | Metallic Ass (5) | Modifidious (5) | Apocalyptica (4) | The Worshyp (4) | Airdash (4) | Mezzrow (4) | White Zombie (4) | DBC (4) | Diamond Plate (4) | Equinox (4) | Excel (4) | Acrophet (4) | Black Track (4) | Panic (4) | Adamantine (4) | Critical Solution (4) | Perzonal War (4) | Phantasm (4) | Shredhead (4) | Steel Fury (4) | Alexander Palitsin (4) | I.N.C. (4) | Wrath (4) | Fight (4) | Kazjurol (4) | King Diamond (4) | Manditory (4) | Allegiance (4) | Altitudes & Attitude (4) | Dead On (4) | Fallout (4) | Hermética (4) | Lethal (4) | Tonic Breed (4) | Wiplash (4) | Animator (4) | Astharoth (4) | Disciples of Power (4) | Extrema (4) | Face of Anger (4) | Fatality (4) | Insecurity (4) | Nasty Savage (4) | Pentagram (4) | Potential Threat (4) | Prophecy (4) | Algebra (4) | Criminal (4) | Nuclear Simphony (4) | Oil (4) | Planleft (4) | Practice to Deceive (4) | Razgate (4) | Revtend (4) | Ritual Servant (4) | Space Chaser (4) | Stormdeath (4) | Teronation (4) | Victim (4) | Vingador (4) | Vulture (4) | Legion (4) | Flacmans Port (4) | Four Noses (4) | Half-Lit (4) | Sabbat (3) | Ancesttral (3) | Target (3) | Симфония Разрушения (3) | Piranha (3) | Hatrix (3) | Souls at Zero (3) | Toranaga (3) | Bitter End (3) | Demolition Train (3) | Killers (3) | Legion (3) | Rhythm of Fear (3) | Sacrifice (3) | Wolfpack Unleashed (3) | Anihilated (3) | Dethrone (3) | Viking (3) | Acridity (3) | Dissolved (3) | Dogma (3) | Exciter (3) | Forced Entry (3) | Nihilist (3) | Quorthon (3) | Taurus (3) | Yosh (3) | Abaxial (3) | Battalion (3) | Disaster Area (3) | Hate FX (3) | Horcas (3) | LawShed (3) | Prowler (3) | Strip Mind (3) | The Force (3) | Glenn Tipton (3) | Next (3) | Against (3) | Deliverance (3) | Hatchet (3) | HI-GH (3) | In Malice's Wake (3) | King Gizzard & the Lizard Wizard (3) | Stone Vengeance (3) | Terror Empire (3) | Thrash Bombz (3) | Thresher (3) | Aleister (3) | Alpha Warhead (3) | Amboog-a-Lard (3) | Anesthesia (3) | Blatant Disarray (3) | Chronical Disturbance (3) | Coldsteel (3) | Cro-Mags (3) | Crossbones (3) | Darkness (3) | DesExult (3) | Disturbed (3) | Drünkards (3) | E.S.T. (3) | Eradicator (3) | F5 (3) | Fierce Allegiance (3) | Filter (3) | Hostile Rage (3) | Incursion Dementa (3) | Jesus Freaks (3) | Metalord (3) | Mystrez (3) | Necrosis (3) | Night Viper (3) | Nightfyre (3) | Serpentor (3) | Total Annihilation (3) | Violator (3)> """

url = 'band/ajax-recommendations/id/' + self.id + '/showMoreSimilar/1'
return SimilarArtists(url, SimilarArtistsResult)


class SimilarArtists(Metallum, list):
"""Entries in the similar artists tab
"""

def __init__(self, url, result_handler):
super().__init__(url)
data = self._content

links_list = PyQuery(data)('a')
values_list = PyQuery(data)('tr')

# assert(len(links_list) == len(values_list) - 1)
for i in range(0, len(links_list) -1):
details = [links_list[i].attrib.get('href')]
details.extend(values_list[i+1].text_content().split('\n')[1:-1])
self.append(result_handler(details))
self.result_count = i

def __repr__(self):

def similar_artist_str(SimilarArtistsResult):
return f'{SimilarArtistsResult.name} ({SimilarArtistsResult.score})'
if not self:
return '<SimilarArtists: None>'
names = list(map(similar_artist_str, self))
s = ' | '.join(names)
return '<SimilarArtists: {0}>'.format(s)


class SimilarArtistsResult(list):
"""Represents a entry in the similar artists tab
"""
_resultType = Band

def __init__(self, details):
super().__init__()
self._details = details
for d in details:
self.append(d)

@property
def id(self) -> str:
# url = PyQuery(self._details[0])('a').attr('href')
return re.search(r'\d+$', self[0]).group(0)

@property
def url(self) -> str:
return 'bands/_/{0}'.format(self.id)

@property
def name(self) -> str:
return self[1]

@property
def country(self) -> str:
"""
>>> search_results[0].country
'United States'
"""
return self[2]

@property
def genres(self) -> List[str]:
return split_genres(self[3])

@property
def score(self) -> int:
return int(self[4])


def __repr__(self):
s = ' | '.join(self[1:])
return '<SimilarArtist: {0}>'.format(s)

def get(self) -> 'Metallum':
return self._resultType(self.url)




class AlbumCollection(MetallumCollection):

Expand Down Expand Up @@ -987,6 +1076,7 @@ def __str__(self):
# Test objects
search_results = band_search('metallica')
band = search_results[0].get()
band.similar_artists
album = band.albums.search(type=AlbumTypes.FULL_LENGTH)[2]
track = album.tracks[0]

Expand Down