5 Scraper for embedded lyrics
8 import sys, os, re, chardet
9 import xml.dom.minidom
as xml
10 from optparse
import OptionParser
11 from common
import utilities
13 __author__ =
"Paul Harrison and 'ronin'"
14 __title__ =
"EmbeddedLyrics"
15 __description__ =
"Search tracks tag for embedded lyrics"
18 __syncronized__ =
True
27 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with Lyrics3/Lyrics3V2 format"))
30 f.seek(-128-9, os.SEEK_END)
32 if (buf !=
"LYRICS200" and buf !=
"LYRICSEND"):
33 f.seek(-9, os.SEEK_END)
35 if (buf ==
"LYRICSEND"):
36 """ Find Lyrics3v1 """
37 f.seek(-5100-9-11, os.SEEK_CUR)
40 start = buf.find(
"LYRICSBEGIN")
41 elif (buf ==
"LYRICS200"):
42 """ Find Lyrics3v2 """
43 f.seek(-9-6, os.SEEK_CUR)
45 f.seek(-size-6, os.SEEK_CUR)
47 if(buf ==
"LYRICSBEGIN"):
52 length = int(buf[3:8])
53 content = buf[8:8+length]
64 pos += string[pos:].
find(
'\x00\x00') + 1
68 return string.find(
'\x00')
71 mins =
"0%s" % int(ms/1000/60)
72 sec =
"0%s" % int((ms/1000)%60)
73 msec =
"0%s" % int((ms%1000)/10)
74 timestamp =
"[%s:%s.%s]" % (mins[-2:],sec[-2:],msec[-2:])
83 utilities.log(
True,
"Failed to import taglib. This grabber requires "
84 "pytaglib TagLib bindings for Python. "
85 "https://github.com/supermihi/pytaglib")
89 utilities.log(debug,
"%s: trying to open %s" % (__title__, filename))
90 f = taglib.File(filename)
94 if tag.startswith(
'LYRICS'):
104 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with ID3v2 format"))
110 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with Flac format"))
116 utilities.log(debug,
"%s: trying %s" % (__title__,
"lyrics embed with MP4 format"))
125 utilities.log(debug,
"%s: searching lyrics for %s - %s - %s" % (__title__, lyrics.artist, lyrics.album, lyrics.title))
128 filename = lyrics.filename.decode(
"utf-8")
130 filename = lyrics.filename
132 ext = os.path.splitext(filename)[1].lower()
142 enc = chardet.detect(lry)
143 lyrics.lyrics = lry.decode(enc[
'encoding'])
162 utilities.log(
True,
"Failed to import taglib. This grabber requires "
163 "pytaglib ? TagLib bindings for Python. "
164 "https://github.com/supermihi/pytaglib")
168 lyrics = utilities.Lyrics()
169 lyrics.source = __title__
170 lyrics.syncronized = __syncronized__
171 lyrics.artist =
'Robb Benson'
172 lyrics.album =
'Demo Tracks'
173 lyrics.title =
'Lone Rock'
174 lyrics.filename = os.path.dirname(os.path.abspath(__file__)) +
'/examples/taglyrics.mp3'
176 found = fetcher.get_lyrics(lyrics)
179 utilities.log(
True,
"Everything appears in order.")
183 utilities.log(
True,
"The lyrics for the test search failed!")
187 from lxml
import etree
188 xml = etree.XML(
u'<lyrics></lyrics>')
189 etree.SubElement(xml,
"artist").text = lyrics.artist
190 etree.SubElement(xml,
"album").text = lyrics.album
191 etree.SubElement(xml,
"title").text = lyrics.title
192 etree.SubElement(xml,
"syncronized").text =
'True' if __syncronized__
else 'False'
193 etree.SubElement(xml,
"grabber").text = lyrics.source
195 lines = lyrics.lyrics.splitlines()
197 etree.SubElement(xml,
"lyric").text = line
199 utilities.log(
True, utilities.convert_etree(etree.tostring(xml, encoding=
'UTF-8',
200 pretty_print=
True, xml_declaration=
True)))
204 from lxml
import etree
205 version = etree.XML(
u'<grabber></grabber>')
206 etree.SubElement(version,
"name").text = __title__
207 etree.SubElement(version,
"author").text = __author__
208 etree.SubElement(version,
"command").text =
'alsong.py'
209 etree.SubElement(version,
"type").text =
'lyrics'
210 etree.SubElement(version,
"description").text = __description__
211 etree.SubElement(version,
"version").text = __version__
212 etree.SubElement(version,
"priority").text = __priority__
213 etree.SubElement(version,
"syncronized").text =
'True' if __syncronized__
else 'False'
215 utilities.log(
True, utilities.convert_etree(etree.tostring(version, encoding=
'UTF-8',
216 pretty_print=
True, xml_declaration=
True)))
222 parser = OptionParser()
224 parser.add_option(
'-v',
"--version", action=
"store_true", default=
False,
225 dest=
"version", help=
"Display version and author")
226 parser.add_option(
'-t',
"--test", action=
"store_true", default=
False,
227 dest=
"test", help=
"Perform self-test for dependencies.")
228 parser.add_option(
'-s',
"--search", action=
"store_true", default=
False,
229 dest=
"search", help=
"Search for lyrics.")
230 parser.add_option(
'-a',
"--artist", metavar=
"ARTIST", default=
None,
231 dest=
"artist", help=
"Artist of track.")
232 parser.add_option(
'-b',
"--album", metavar=
"ALBUM", default=
None,
233 dest=
"album", help=
"Album of track.")
234 parser.add_option(
'-n',
"--title", metavar=
"TITLE", default=
None,
235 dest=
"title", help=
"Title of track.")
236 parser.add_option(
'-f',
"--filename", metavar=
"FILENAME", default=
None,
237 dest=
"filename", help=
"Filename of track.")
238 parser.add_option(
'-d',
'--debug', action=
"store_true", default=
False,
239 dest=
"debug", help=(
"Show debug messages"))
241 opts, args = parser.parse_args()
243 lyrics = utilities.Lyrics()
244 lyrics.source = __title__
245 lyrics.syncronized = __syncronized__
257 lyrics.artist = opts.artist
259 lyrics.album = opts.album
261 lyrics.title = opts.title
263 lyrics.filename = opts.filename
266 if fetcher.get_lyrics(lyrics):
270 utilities.log(
True,
"No lyrics found for this track")
273 if __name__ ==
'__main__':