Page 1 of 1

Batch Artist Art Finder - Does it exist?

Posted: Thu Nov 05, 2009 10:31 am
by Superdude
I have the following Setup:
C:\MP3\Genre\Artist\Album\# - Title

Is there a media monkey script that will search google images or other sites such as HTbackdrops for the Band/Artist Pics and place them in the Artist node as folder.jpg or artist.jpg?
I was hoping to find something like the Batch Art Finder but for Artists.

Thanks!
John

Re: Batch Artist Art Finder - Does it exist?

Posted: Thu Nov 05, 2009 10:58 am
by nynaevelan
I too would like to see something like this.

Re: Batch Artist Art Finder - Does it exist?

Posted: Fri Nov 06, 2009 5:48 am
by trixmoto
This would certainly be possible, but as far as I'm aware it doesn't currently exist. Last.Fm also has images within it's artist information web service, so this is another potential source.

Re: Batch Artist Art Finder - Does it exist?

Posted: Fri Nov 06, 2009 9:37 am
by Superdude
I should have elaborated on why this would be a good feature to add:

1) It would allow people to have a folder thumb of the artist. Sometimes a visual is easier to spot than an actual name in windows.
2) I run xbmc which has a library function. However, I have over 400 gigs of music I converted from cds. This is killing my xbox. Since it supports folder thumbs, this would work as a nice workaround.
3) This can open up media monkey to have backdrops of the artist when playing songs. It would look really nice.

HTbackdrops has the nicest backdrops. It might be too big for thumbs.
Google Images - Good source but you have to always look through everything
Discogs? - Might be potential here.

Re: Batch Artist Art Finder - Does it exist?

Posted: Fri Nov 06, 2009 6:35 pm
by Owyn
I took a quick look at HTbackdrops. Their thumbnails are 100x56.

Re: Batch Artist Art Finder - Does it exist?

Posted: Sat Nov 21, 2009 7:31 pm
by lf0
Some time ago I hacked together a little python script to do the job (disclaimer: it was just a couple of minutes work so no warranty ;-)) that gets pictures from last.fm and writes them to Artist/folder.jpg.


Save as getartist.py


You need to install Python 2.6 and the Python Imaging Library (PIL).
You also need to fetch pylast.py. Put the pylast.py in the same folder as getartist.py (or install pylast properly) and tweak getartist.py as you like (in particular START_DIR when you don't run it from your root music folder).

You should also change the API_KEY (get your own one) but it should work as it is.

It uses last.fm to fetch the artist images and you need to have your music stored as START_DIR/Genre/Artist/.
I apply a stupid heuristic to make the image quadratic (just use the maximum square in the center) and scales it down (or up) to 500x500 px.

Maybe it's useful for you - it did the job for me.

Re: Batch Artist Art Finder - Does it exist?

Posted: Tue Nov 24, 2009 3:10 pm
by fizzjob
I tried running that python script, but I get "tuple indices must be integers, not str" for each artist. I don't really know enough about python to effectively troubleshoot that...any ideas?

Re: Batch Artist Art Finder - Does it exist?

Posted: Wed Nov 25, 2009 9:10 am
by lf0
fizzjob wrote:I tried running that python script, but I get "tuple indices must be integers, not str" for each artist. I don't really know enough about python to effectively troubleshoot that...any ideas?
If you could provide the line number in which the error occurred and maybe your directory layout (or what you "tweaked") I might be able to fix it.

Re: Batch Artist Art Finder - Does it exist?

Posted: Wed Nov 25, 2009 9:44 am
by fizzjob
lf0 wrote:
fizzjob wrote:I tried running that python script, but I get "tuple indices must be integers, not str" for each artist. I don't really know enough about python to effectively troubleshoot that...any ideas?
If you could provide the line number in which the error occurred and maybe your directory layout (or what you "tweaked") I might be able to fix it.
My directory layout is pretty simple:

D:\unsorted\country\artist\album

All I've changed aside from the API key:

Code: Select all

START_DIR = "." # Directory to start scanning
USE_GENRE = False # When True look for START_DIR/Genre/Artist otherwise just use START_DIR/Artist
WRITE_DIRECTORY_ENTRY = False # Write extra PNG file and create .directory file
JPG_FILENAME = "artist.jpg"
PNG_FILENAME = "artist.png"
and the output is like so:

Code: Select all

D:\unsorted\country>c:\Python26\python.exe getartist.py
Frankie Laine... could not convert image
tuple indices must be integers, not str
Hank Williams... could not convert image
tuple indices must be integers, not str
Johnny Cash... could not convert image
tuple indices must be integers, not str
Johnny Horton... could not convert image
tuple indices must be integers, not str
pylast-read-only... could not convert image
Invalid artist name supplied
Willie Nelson... could not convert image
tuple indices must be integers, not str
If I run python with the -v to generate verbose output:

Code: Select all

c:\Python26\python.exe -v getartist.py
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# c:\Python26\lib\site.pyc matches c:\Python26\lib\site.py
import site # precompiled from c:\Python26\lib\site.pyc
# c:\Python26\lib\os.pyc matches c:\Python26\lib\os.py
import os # precompiled from c:\Python26\lib\os.pyc
import errno # builtin
import nt # builtin
# c:\Python26\lib\ntpath.pyc matches c:\Python26\lib\ntpath.py
import ntpath # precompiled from c:\Python26\lib\ntpath.pyc
# c:\Python26\lib\stat.pyc matches c:\Python26\lib\stat.py
import stat # precompiled from c:\Python26\lib\stat.pyc
# c:\Python26\lib\genericpath.pyc matches c:\Python26\lib\genericpath.py
import genericpath # precompiled from c:\Python26\lib\genericpath.pyc
# c:\Python26\lib\warnings.pyc matches c:\Python26\lib\warnings.py
import warnings # precompiled from c:\Python26\lib\warnings.pyc
# c:\Python26\lib\linecache.pyc matches c:\Python26\lib\linecache.py
import linecache # precompiled from c:\Python26\lib\linecache.pyc
# c:\Python26\lib\types.pyc matches c:\Python26\lib\types.py
import types # precompiled from c:\Python26\lib\types.pyc
# c:\Python26\lib\UserDict.pyc matches c:\Python26\lib\UserDict.py
import UserDict # precompiled from c:\Python26\lib\UserDict.pyc
# c:\Python26\lib\_abcoll.pyc matches c:\Python26\lib\_abcoll.py
import _abcoll # precompiled from c:\Python26\lib\_abcoll.pyc
# c:\Python26\lib\abc.pyc matches c:\Python26\lib\abc.py
import abc # precompiled from c:\Python26\lib\abc.pyc
# c:\Python26\lib\copy_reg.pyc matches c:\Python26\lib\copy_reg.py
import copy_reg # precompiled from c:\Python26\lib\copy_reg.pyc
# c:\Python26\lib\locale.pyc matches c:\Python26\lib\locale.py
import locale # precompiled from c:\Python26\lib\locale.pyc
import encodings # directory c:\Python26\lib\encodings
# c:\Python26\lib\encodings\__init__.pyc matches c:\Python26\lib\encodings\__init__.py
import encodings # precompiled from c:\Python26\lib\encodings\__init__.pyc
# c:\Python26\lib\codecs.pyc matches c:\Python26\lib\codecs.py
import codecs # precompiled from c:\Python26\lib\codecs.pyc
import _codecs # builtin
# c:\Python26\lib\encodings\aliases.pyc matches c:\Python26\lib\encodings\aliases.py
import encodings.aliases # precompiled from c:\Python26\lib\encodings\aliases.pyc
# c:\Python26\lib\functools.pyc matches c:\Python26\lib\functools.py
import functools # precompiled from c:\Python26\lib\functools.pyc
import _functools # builtin
import _locale # builtin
# c:\Python26\lib\re.pyc matches c:\Python26\lib\re.py
import re # precompiled from c:\Python26\lib\re.pyc
# c:\Python26\lib\sre_compile.pyc matches c:\Python26\lib\sre_compile.py
import sre_compile # precompiled from c:\Python26\lib\sre_compile.pyc
import _sre # builtin
# c:\Python26\lib\sre_parse.pyc matches c:\Python26\lib\sre_parse.py
import sre_parse # precompiled from c:\Python26\lib\sre_parse.pyc
# c:\Python26\lib\sre_constants.pyc matches c:\Python26\lib\sre_constants.py
import sre_constants # precompiled from c:\Python26\lib\sre_constants.pyc
import operator # builtin
# c:\Python26\lib\encodings\cp1252.pyc matches c:\Python26\lib\encodings\cp1252.py
import encodings.cp1252 # precompiled from c:\Python26\lib\encodings\cp1252.pyc
Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
import PIL # directory c:\Python26\lib\site-packages\PIL
# c:\Python26\lib\site-packages\PIL\__init__.pyc matches c:\Python26\lib\site-packages\PIL\__init__.py
import PIL # precompiled from c:\Python26\lib\site-packages\PIL\__init__.pyc
# c:\Python26\lib\site-packages\PIL\Image.pyc matches c:\Python26\lib\site-packages\PIL\Image.py
import PIL.Image # precompiled from c:\Python26\lib\site-packages\PIL\Image.pyc
# c:\Python26\lib\lib-tk\FixTk.pyc matches c:\Python26\lib\lib-tk\FixTk.py
import FixTk # precompiled from c:\Python26\lib\lib-tk\FixTk.pyc
import ctypes # directory c:\Python26\lib\ctypes
# c:\Python26\lib\ctypes\__init__.pyc matches c:\Python26\lib\ctypes\__init__.py
import ctypes # precompiled from c:\Python26\lib\ctypes\__init__.pyc
import _ctypes # dynamically loaded from c:\Python26\DLLs\_ctypes.pyd
# c:\Python26\lib\struct.pyc matches c:\Python26\lib\struct.py
import struct # precompiled from c:\Python26\lib\struct.pyc
import _struct # builtin
# c:\Python26\lib\ctypes\_endian.pyc matches c:\Python26\lib\ctypes\_endian.py
import ctypes._endian # precompiled from c:\Python26\lib\ctypes\_endian.pyc
import _tkinter # dynamically loaded from c:\Python26\DLLs\_tkinter.pyd
import PIL._imaging # dynamically loaded from c:\Python26\lib\site-packages\PIL\_imaging.pyd
# c:\Python26\lib\site-packages\PIL\ImageMode.pyc matches c:\Python26\lib\site-packages\PIL\ImageMode.py
import PIL.ImageMode # precompiled from c:\Python26\lib\site-packages\PIL\ImageMode.pyc
# c:\Python26\lib\site-packages\PIL\ImagePalette.pyc matches c:\Python26\lib\site-packages\PIL\ImagePalette.py
import PIL.ImagePalette # precompiled from c:\Python26\lib\site-packages\PIL\ImagePalette.pyc
import array # builtin
# c:\Python26\lib\string.pyc matches c:\Python26\lib\string.py
import string # precompiled from c:\Python26\lib\string.pyc
import strop # builtin
# c:\Python26\lib\site-packages\PIL\ImageFile.pyc matches c:\Python26\lib\site-packages\PIL\ImageFile.py
import ImageFile # precompiled from c:\Python26\lib\site-packages\PIL\ImageFile.pyc
# c:\Python26\lib\site-packages\PIL\Image.pyc matches c:\Python26\lib\site-packages\PIL\Image.py
import Image # precompiled from c:\Python26\lib\site-packages\PIL\Image.pyc
import _imaging # previously loaded (c:\Python26\lib\site-packages\PIL\_imaging.pyd)
# c:\Python26\lib\site-packages\PIL\ImageMode.pyc matches c:\Python26\lib\site-packages\PIL\ImageMode.py
import ImageMode # precompiled from c:\Python26\lib\site-packages\PIL\ImageMode.pyc
# c:\Python26\lib\site-packages\PIL\ImagePalette.pyc matches c:\Python26\lib\site-packages\PIL\ImagePalette.py
import ImagePalette # precompiled from c:\Python26\lib\site-packages\PIL\ImagePalette.pyc
# c:\Python26\lib\traceback.pyc matches c:\Python26\lib\traceback.py
import traceback # precompiled from c:\Python26\lib\traceback.pyc
import pylast # precompiled from D:\unsorted\country\pylast.pyc
# c:\Python26\lib\hashlib.pyc matches c:\Python26\lib\hashlib.py
import hashlib # precompiled from c:\Python26\lib\hashlib.pyc
import _hashlib # dynamically loaded from c:\Python26\DLLs\_hashlib.pyd
# c:\Python26\lib\httplib.pyc matches c:\Python26\lib\httplib.py
import httplib # precompiled from c:\Python26\lib\httplib.pyc
# c:\Python26\lib\socket.pyc matches c:\Python26\lib\socket.py
import socket # precompiled from c:\Python26\lib\socket.pyc
import _socket # dynamically loaded from c:\Python26\DLLs\_socket.pyd
import _ssl # dynamically loaded from c:\Python26\DLLs\_ssl.pyd
import cStringIO # builtin
# c:\Python26\lib\urlparse.pyc matches c:\Python26\lib\urlparse.py
import urlparse # precompiled from c:\Python26\lib\urlparse.pyc
# c:\Python26\lib\collections.pyc matches c:\Python26\lib\collections.py
import collections # precompiled from c:\Python26\lib\collections.pyc
import _collections # builtin
# c:\Python26\lib\keyword.pyc matches c:\Python26\lib\keyword.py
import keyword # precompiled from c:\Python26\lib\keyword.pyc
# c:\Python26\lib\mimetools.pyc matches c:\Python26\lib\mimetools.py
import mimetools # precompiled from c:\Python26\lib\mimetools.pyc
# c:\Python26\lib\tempfile.pyc matches c:\Python26\lib\tempfile.py
import tempfile # precompiled from c:\Python26\lib\tempfile.pyc
# c:\Python26\lib\random.pyc matches c:\Python26\lib\random.py
import random # precompiled from c:\Python26\lib\random.pyc
# c:\Python26\lib\__future__.pyc matches c:\Python26\lib\__future__.py
import __future__ # precompiled from c:\Python26\lib\__future__.pyc
import math # builtin
import binascii # builtin
import _random # builtin
import thread # builtin
# c:\Python26\lib\rfc822.pyc matches c:\Python26\lib\rfc822.py
import rfc822 # precompiled from c:\Python26\lib\rfc822.pyc
import time # builtin
# c:\Python26\lib\ssl.pyc matches c:\Python26\lib\ssl.py
import ssl # precompiled from c:\Python26\lib\ssl.pyc
# c:\Python26\lib\textwrap.pyc matches c:\Python26\lib\textwrap.py
import textwrap # precompiled from c:\Python26\lib\textwrap.pyc
# c:\Python26\lib\base64.pyc matches c:\Python26\lib\base64.py
import base64 # precompiled from c:\Python26\lib\base64.pyc
# c:\Python26\lib\urllib.pyc matches c:\Python26\lib\urllib.py
import urllib # precompiled from c:\Python26\lib\urllib.pyc
# c:\Python26\lib\nturl2path.pyc matches c:\Python26\lib\nturl2path.py
import nturl2path # precompiled from c:\Python26\lib\nturl2path.pyc
# c:\Python26\lib\threading.pyc matches c:\Python26\lib\threading.py
import threading # precompiled from c:\Python26\lib\threading.pyc
import xml # directory c:\Python26\lib\xml
# c:\Python26\lib\xml\__init__.pyc matches c:\Python26\lib\xml\__init__.py
import xml # precompiled from c:\Python26\lib\xml\__init__.pyc
import xml.dom # directory c:\Python26\lib\xml\dom
# c:\Python26\lib\xml\dom\__init__.pyc matches c:\Python26\lib\xml\dom\__init__.py
import xml.dom # precompiled from c:\Python26\lib\xml\dom\__init__.pyc
# c:\Python26\lib\xml\dom\domreg.pyc matches c:\Python26\lib\xml\dom\domreg.py
import xml.dom.domreg # precompiled from c:\Python26\lib\xml\dom\domreg.pyc
# c:\Python26\lib\xml\dom\minicompat.pyc matches c:\Python26\lib\xml\dom\minicompat.py
import xml.dom.minicompat # precompiled from c:\Python26\lib\xml\dom\minicompat.pyc
# c:\Python26\lib\xml\dom\minidom.pyc matches c:\Python26\lib\xml\dom\minidom.py
import xml.dom.minidom # precompiled from c:\Python26\lib\xml\dom\minidom.pyc
# c:\Python26\lib\xml\dom\xmlbuilder.pyc matches c:\Python26\lib\xml\dom\xmlbuilder.py
import xml.dom.xmlbuilder # precompiled from c:\Python26\lib\xml\dom\xmlbuilder.pyc
# c:\Python26\lib\copy.pyc matches c:\Python26\lib\copy.py
import copy # precompiled from c:\Python26\lib\copy.pyc
# c:\Python26\lib\xml\dom\NodeFilter.pyc matches c:\Python26\lib\xml\dom\NodeFilter.py
import xml.dom.NodeFilter # precompiled from c:\Python26\lib\xml\dom\NodeFilter.pyc
# c:\Python26\lib\shelve.pyc matches c:\Python26\lib\shelve.py
import shelve # precompiled from c:\Python26\lib\shelve.pyc
import cPickle # builtin
# c:\Python26\lib\htmlentitydefs.pyc matches c:\Python26\lib\htmlentitydefs.py
import htmlentitydefs # precompiled from c:\Python26\lib\htmlentitydefs.pyc
# c:\Python26\lib\urllib2.pyc matches c:\Python26\lib\urllib2.py
import urllib2 # precompiled from c:\Python26\lib\urllib2.pyc
# c:\Python26\lib\posixpath.pyc matches c:\Python26\lib\posixpath.py
import posixpath # precompiled from c:\Python26\lib\posixpath.pyc
# c:\Python26\lib\bisect.pyc matches c:\Python26\lib\bisect.py
import bisect # precompiled from c:\Python26\lib\bisect.pyc
import _bisect # builtin
# c:\Python26\lib\encodings\utf_8.pyc matches c:\Python26\lib\encodings\utf_8.py
import encodings.utf_8 # precompiled from c:\Python26\lib\encodings\utf_8.pyc
# c:\Python26\lib\encodings\cp437.pyc matches c:\Python26\lib\encodings\cp437.py
import encodings.cp437 # precompiled from c:\Python26\lib\encodings\cp437.pyc
Frankie Laine...# c:\Python26\lib\encodings\ascii.pyc matches c:\Python26\lib\encodings\ascii.py
import encodings.ascii # precompiled from c:\Python26\lib\encodings\ascii.pyc
# c:\Python26\lib\xml\dom\expatbuilder.pyc matches c:\Python26\lib\xml\dom\expatbuilder.py
import xml.dom.expatbuilder # precompiled from c:\Python26\lib\xml\dom\expatbuilder.pyc
import xml.parsers # directory c:\Python26\lib\xml\parsers
# c:\Python26\lib\xml\parsers\__init__.pyc matches c:\Python26\lib\xml\parsers\__init__.py
import xml.parsers # precompiled from c:\Python26\lib\xml\parsers\__init__.pyc
# c:\Python26\lib\xml\parsers\expat.pyc matches c:\Python26\lib\xml\parsers\expat.py
import xml.parsers.expat # precompiled from c:\Python26\lib\xml\parsers\expat.pyc
import pyexpat # dynamically loaded from c:\Python26\DLLs\pyexpat.pyd
 could not convert image
tuple indices must be integers, not str
Hank Williams... could not convert image
tuple indices must be integers, not str
Johnny Cash... could not convert image
tuple indices must be integers, not str
Johnny Horton... could not convert image
tuple indices must be integers, not str
pylast-read-only... could not convert image
Invalid artist name supplied
Willie Nelson... could not convert image
tuple indices must be integers, not str
# clear __builtin__._
# clear sys.path
# clear sys.argv
# clear sys.ps1
# clear sys.ps2
# clear sys.exitfunc
# clear sys.exc_type
# clear sys.exc_value
# clear sys.exc_traceback
# clear sys.last_type
# clear sys.last_value
# clear sys.last_traceback
# clear sys.path_hooks
# clear sys.path_importer_cache
# clear sys.meta_path
# clear sys.flags
# clear sys.float_info
# restore sys.stdin
# restore sys.stdout
# restore sys.stderr
# cleanup __main__
# cleanup[1] _bisect
# cleanup[1] PIL
# cleanup[1] zipimport
# cleanup[1] signal
# cleanup[1] pylast
# cleanup[1] ImageFile
# cleanup[1] threading
# cleanup[1] cStringIO
# cleanup[1] locale
# cleanup[1] encodings
# cleanup[1] abc
# cleanup[1] math
# cleanup[1] _ctypes
# cleanup[1] _functools
# cleanup[1] _locale
# cleanup[1] traceback
# cleanup[1] __future__
# cleanup[1] _collections
# cleanup[1] operator
# cleanup[1] encodings.cp437
# cleanup[1] sre_constants
# cleanup[1] _warnings
# cleanup[1] cPickle
# cleanup[1] _codecs
# cleanup[1] encodings.cp1252
# cleanup[1] nturl2path
# cleanup[1] _struct
# cleanup[1] keyword
# cleanup[1] encodings.aliases
# cleanup[1] shelve
# cleanup[1] exceptions
# cleanup[1] FixTk
# cleanup[1] site
# cleanup[1] pyexpat
# cleanup[1] strop
# cleanup[1] nt
# cleanup[1] encodings.ascii
# cleanup[1] htmlentitydefs
# cleanup[1] urllib2
# cleanup[1] encodings.utf_8
# cleanup[1] urlparse
# cleanup[1] functools
# cleanup[1] random
# cleanup[1] urllib
# cleanup[1] collections
# cleanup[1] httplib
# cleanup[1] bisect
# cleanup[1] _tkinter
# cleanup[1] ctypes
# cleanup[1] codecs
# cleanup[1] socket
# cleanup[1] posixpath
# cleanup[1] _socket
# cleanup[1] hashlib
# cleanup[1] mimetools
# cleanup[1] _hashlib
# cleanup[1] _random
# cleanup[1] ctypes._endian
# cleanup[1] tempfile
# cleanup[1] ssl
# cleanup[1] rfc822
# cleanup[1] thread
# cleanup[1] _ssl
# cleanup[1] time
# cleanup[1] base64
# cleanup[1] textwrap
# cleanup[1] binascii
# cleanup[1] struct
# cleanup[2] xml
# cleanup[2] pyexpat.errors
# cleanup[2] string
# cleanup[2] pyexpat.model
# cleanup[2] PIL.ImageMode
# cleanup[2] xml.parsers.expat
# cleanup[2] PIL._imaging
# cleanup[2] _imaging
# cleanup[2] re
# cleanup[2] ntpath
# cleanup[2] UserDict
# cleanup[2] PIL.Image
# cleanup[2] xml.dom.domreg
# cleanup[2] Image
# cleanup[2] ImagePalette
# cleanup[2] xml.dom.xmlbuilder
# cleanup[2] os
# cleanup[2] xml.dom.expatbuilder
# cleanup[2] xml.dom
# cleanup[2] _sre
# cleanup[2] PIL.ImagePalette
# cleanup[2] xml.parsers
# cleanup[2] array
# cleanup[2] errno
# cleanup[2] os.path
# cleanup[2] xml.dom.NodeFilter
# cleanup[2] copy
# cleanup[2] xml.dom.minidom
# cleanup[2] sre_parse
# cleanup[2] copy_reg
# cleanup[2] sre_compile
# cleanup[2] _abcoll
# cleanup[2] xml.dom.minicompat
# cleanup[2] genericpath
# cleanup[2] stat
# cleanup[2] warnings
# cleanup[2] types
# cleanup[2] ImageMode
# cleanup[2] linecache
# cleanup sys
# cleanup __builtin__
# cleanup ints: 53 unfreed ints
# cleanup floats: 34 unfreed floats
I don't see what line number is having the trouble, specifically.

Re: Batch Artist Art Finder - Does it exist?

Posted: Sat Nov 28, 2009 6:49 am
by lf0
I should have tested it with Python 2.6 when recommending to install it :oops:
Problem was, that the pylast.py I use has a different behavior under Python 2.6 as it seems.

Updated getartist.py

Hopefully this will work now.

Re: Batch Artist Art Finder - Does it exist?

Posted: Sat Nov 28, 2009 9:58 am
by nynaevelan
How do you run this??

Re: Batch Artist Art Finder - Does it exist?

Posted: Mon Nov 30, 2009 10:16 am
by fizzjob
lf0 wrote:I should have tested it with Python 2.6 when recommending to install it :oops:
Problem was, that the pylast.py I use has a different behavior under Python 2.6 as it seems.

Updated getartist.py

Hopefully this will work now.
That did it, thanks!

Re: Batch Artist Art Finder - Does it exist?

Posted: Mon Nov 30, 2009 10:20 am
by fizzjob
nynaevelan wrote:How do you run this??
Assuming you've installed python and the other dependencies (see lf0's first post in this thread about that), just run...

Code: Select all

python.exe getartist.py
...in a command prompt. You may need to specify the path to where python.exe is ("c:\python26\python.exe getartist.py").

Re: Batch Artist Art Finder - Does it exist?

Posted: Mon Nov 30, 2009 10:41 am
by nynaevelan
Thanks I will try that but since I was able to use Helium to download the artist pics I may not need to use this one, but thanks again.

Re: Batch Artist Art Finder - Does it exist?

Posted: Mon Nov 30, 2009 12:33 pm
by fizzjob
When I was running this, I noticed it failed on anything that ended in a trailing "The". I modified the code a bit (my first attempt at digging into Python), and it seems to work. I set it to work with a structure of StartDir/Artist/Album, which is different from how lf0 has it.

Code: Select all

#!/usr/bin/python
# Very basic python script to fetch artist images from last.fm
# - You need PIL from http://www.pythonware.com/products/pil
# - You need pylast from http://code.google.com/p/pylast/
#   or just http://pylast.googlecode.com/svn/trunk/pylast.py

from httplib import InvalidURL
from os import listdir
from os import path
from os import stat
from stat import ST_MODE
from stat import S_ISDIR
from sys import stdout, version_info
from urllib2 import HTTPError
from urllib2 import Request
from urllib2 import URLError
from urllib2 import urlopen

from ImageFile import Parser
from PIL import Image
from pylast import Artist
from pylast import get_lastfm_network

# basic tweaks
START_DIR = "." # Directory to start scanning
USE_GENRE = False # When True look for START_DIR/Genre/Artist otherwise just use START_DIR/Artist
WRITE_DIRECTORY_ENTRY = False # Write extra PNG file and create .directory file
JPG_FILENAME = "artist.jpg"
PNG_FILENAME = "artist.png"

# You have to have your own unique two values for API_KEY and API_SECRET
# Obtain yours from http://www.last.fm/api/account for Last.fm
API_KEY = "1caaaecb5f85df41359680c0b95191af" # this is a sample key
API_SECRET = "c3f6a6e65a796e813b6c9a2c91e85d79"

def fetch_image(url):
    """
    Retrieve a image given by the url.
    """
    tries = 0
    if not url.startswith('http://'):
        return None
    while True:
        try:
            request = Request(url)
            reply = urlopen(request)
            p = Parser()
            while 1:
                s = reply.read(1024)
                if not s:
                    break
                p.feed(s)
            im = p.close()
            return im
        except (URLError, HTTPError, InvalidURL), e:
            tries += 1
            if tries >= 3:
                print 'error while fetching: %s (%s)' % (url, e)
                return None
        finally:
            if 'reply' in locals():
                reply.close()

def get_image(artistName):
    artist = Artist(artistName, get_lastfm_network(API_KEY, API_SECRET))
    image_list = artist.get_images(limit=1)
    if version_info[1] >= 6 and version_info[0] < 3:
        url = image_list[0].sizes.original
    else:
        url = image_list[0]["sizes"]["original"]
    return fetch_image(url)

def write_directory(dir):
    file = open(path.join(dir, ".directory"), "w")
    file.write("[Desktop Entry]\n")
    file.write("Icon=./%s\n" % PNG_FILENAME)
    file.close()

def save_image(prefix, artistName, size=500):
    if artistName.endswith(", The"):
       idx = artistName.find(", The")
       artistName2 = "The " + artistName[0:idx]
    else:
       artistName2 = artistName
    print "%s.." % artistName2,
    directory = path.join(prefix, artistName)
    jpgFile = path.join(directory, JPG_FILENAME)
    pngFile = path.join(directory, PNG_FILENAME)
    if path.exists(jpgFile) or (WRITE_DIRECTORY_ENTRY and path.exists(pngFile)):
        print "image exists"
        return
    stdout.flush()
    try:
        image = get_image(artistName2)
        (w, h) = image.size
        # crop only the center of the image
        if (w > h):
            result = image.crop(((w-h) / 2, 0, (w + h) / 2, h))
        else:
            result = image.crop((0, (h-w) / 2, w, (w + h) / 2))
        if result.mode != "RGB":
            result = result.convert("RGB")
        result = result.resize((size, size), Image.BICUBIC)
        result.save(jpgFile, "JPEG")
        if WRITE_DIRECTORY_ENTRY:
            result.save(pngFile, "PNG")
            write_directory(directory)
        print "ok"
    except (IOError), e:
        print "could not save image"
        print e
    except (Exception), e:
        print "could not convert image"
        print e

def walk_artists(dir):
    dirList = listdir(dir)
    for artistName in dirList:
        artistDir = path.join(dir, artistName)
        mode = stat(artistDir)[ST_MODE]
        if S_ISDIR(mode):
            save_image(dir, artistName.decode('utf-8'))

def walk_genres(dir):
    dirList = listdir(dir)
    for genreName in dirList:
        genreDir = path.join(dir, genreName)
        mode = stat(genreName)[ST_MODE]
        if S_ISDIR(mode):
            walk_artists(genreDir)

if __name__ == "__main__":
    if USE_GENRE:
        walk_genres(START_DIR)
    else:
        walk_artists(START_DIR)