使用python部分下载提取MP3 URL的ID3标签

时间:2014-11-12 14:26:26

标签: python metadata id3 mutagen

我需要提取远程mp3文件的ID3标签和元数据。

我写了几行可以获取本地文件的ID3标签:

from mutagen.mp3 import MP3
import urllib2

audio = MP3("Whistle.mp3")

songtitle = audio["TIT2"]
artist = audio["TPE1"]

print "Title: " + str(songtitle)
print "Artist: "+str(artist)

我需要为mp3文件的url链接实现此目的。我试图使用urllib2部分下载文件。

import urllib2
from mutagen.mp3 import MP3

req = urllib2.Request('http://www.1songday.com/wp-content/uploads/2013/08/Lorde-Royals.mp3')
req.headers['Range'] = 'bytes=%s-%s' % (0, 100)
response = urllib2.urlopen(req)
headers = response.info()
print headers.type
print headers.maintype

data = response.read()
print len(data)

如何在不完全下载文件的情况下提取MP3网址的ID3标签?

2 个答案:

答案 0 :(得分:0)

在您的示例中,未提取ID3标记,因此您无法提取它们。

在阅读了ID3的规格之后我玩了一下,这是一个很好的入门方式。

#Search for ID3v1 tags
import string
tagIndex = string.find(data,'TAG')
if (tagIndex>0):
  if data[tagIndex+3]=='+': 
    print "Found extended ID3v1 tag!"
    title = data[tagIndex+3:tagIndex+63]
    print title
  else:
    print  "Found ID3v1 tags"
    title = data[tagIndex+3:tagIndex+33]
    print title
    #So on.
else:
  #Look for ID3v2 tags
  if 'TCOM' in data:
    composerIndex = string.find(data,'TCOM')
    #and so on. See wikipedia for a full list of frame specifications

答案 1 :(得分:0)

id3标签存储在ID3元数据中,该元数据通常位于mp3帧的前面中(包含音频),但mp3标准也允许它们"follow the mp3 frames"

要下载所需的最小字节数:

  1. 下载mp3的前10个字节,提取ID3v2标头并计算id3v2标头的大小
  2. 检索完整的id3v2标签下载{/ 1}}个字节的mp3
  3. 使用python库提取ID3标签
  4. 这是一个脚本(python 2或3),它以最小的下载大小提取专辑封面:

    size

    一些评论:

    • 它检查ID3是否在文件前面,并且它是ID3v2
    • id3标签的大小存储在字节6到9中,如documented on id3.org
    • 不幸的是,mutagen需要一个完整的mp3音频帧来解析id3标签。因此,您还需要下载一个mp3帧(根据this comment最长为2881字节)
    • 而不是盲目地假设专辑封面是jpg,你应首先检查图像格式为id3 allows many different image types
    • 使用来自互联网的大约10个随机mp3进行测试,例如这一个:try: import urllib2 as request # python 2 except ImportError: from urllib import request # python 3 from functools import reduce import sys from io import BytesIO from mutagen.mp3 import MP3 url = sys.argv[1] def get_n_bytes(url, size): req = request.Request(url) req.headers['Range'] = 'bytes=%s-%s' % (0, size-1) response = request.urlopen(req) return response.read() data = get_n_bytes(url, 10) if data[0:3] != 'ID3': raise Exception('ID3 not in front of mp3 file') size_encoded = bytearray(data[-4:]) size = reduce(lambda a,b: a*128+b, size_encoded, 0) header = BytesIO() # mutagen needs one full frame in order to function. Add max frame size data = get_n_bytes(url, size+2881) header.write(data) header.seek(0) f = MP3(header) if f.tags and 'APIC:' in f.tags.keys(): artwork = f.tags['APIC:'].data with open('image.jpg', 'wb') as img: img.write(artwork)