使用Python下载歌词并嵌入歌曲文件中的实现代码


Posted in Python onNovember 13, 2015

使用python扫描本地音乐并下载歌词
这次这个真的是干货哦,昨晚弄了半晚上,,,,从8点吃完饭就开始写,一直到了快12点才弄好,,,新手,伤不起呀。。。。
先简单的说下吧,百度提供了一个音乐搜索的api,你想百度请求类似于

http://box.zhangmen.baidu.com/x?op=12&count=1&title=最佳损友$$陈奕迅$$$$

的地址,百度会给你返回一段xml,如下所示

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<result>
<count>1</count>
<url>
<encode>
<![CDATA[
http://zhangmenshiting.baidu.com/data2/music/12762845/YmRqamdua21fn6NndK6ap5WXcJlrmG1xlJhobWibmGpjk5ZtmWiZcWRjZ5lqbGyelGKWlZtubGljZ5lka2uanWSXY1qin5t1YWBmZW5ocGlhaWdnbGtqbzE$
]]>
</encode>
<decode>
<![CDATA[
12762845.mp3?xcode=e6b69cf593ea22ac9d2b9314e565fc0caf85125f065ce3e0&mid=0.31929107437537
]]>
</decode>
<type>8</type>
<lrcid>2829</lrcid>
<flag>1</flag>
</url>
<durl>
<encode>
<![CDATA[
http://zhangmenshiting2.baidu.com/data2/music/7345405/aGVnaWlmbGaeomZzrZmmnJZvmGqXbHCbl2dsZ5qXaWqSlWpsmmdrb2mXamxpbXCclGNsmW2ba25mYmxtapmZcWqTWaGemnRoX2VkbWdvaGhoZmZramluOA$$
]]>
</encode>
<decode>
<![CDATA[
7345405.mp3?xcode=e6b69cf593ea22ac78e1478e78479dc19e8e4650995cb99a&mid=0.31929107437537
]]>
</decode>
<type>8</type>
<lrcid>2829</lrcid>
<flag>1</flag>
</durl>
<p2p>
<hash>f98b6772aa97966550ec80617879becee0233bf4</hash>
<url>
<![CDATA[ ]]>
</url>
<type>mp3</type>
<size>3778335</size>
<bitrate>128</bitrate>
</p2p>
</result>

简单的说明下,由于我们要做的只是获取到歌曲的lrc歌词地址,所以有用的只有2829这个标签。
而encode和decode里面的拼接起来就是mp3的下载地址,如本例的

http://zhangmenshiting.baidu.com/data2/music/12762845/YmRqamdua21fn6NndK6ap5WXcJlrmG1xlJhobWibmGpjk5ZtmWiZcWRjZ5lqbGyelGKWlZtubGljZ5lka2uanWSXY1qin5t1YWBmZW5ocGlhaWdnbGtqbzE$12762845.mp3?xcode=e6b69cf593ea22ac9d2b9314e565fc0caf85125f065ce3e0&mid=0.31929107437537

就是下载地址,不过音质太差,有时间在研究下这个。
继续说歌词,注意lrcid标签里面的2829
http://box.zhangmen.baidu.com/bdlrc/ 这个是百度lrc歌词存放地址,
然后本例的歌词地址是http://box.zhangmen.baidu.com/bdlrc/28/2829.lrc
看到了吧,歌词地址后面的两个数字的计算方法是在lrcid除以100所获得的整数,就是第一个数字,然后第二个数字就是lrcid,然后后面加上后缀.lrc就搞定了
获得lrc地址之后就简单了,只要请求该地址,然后将获取到的内容写入文件就ok了。
好了,大概就是这样,下面是代码

import os
import os.path
import re
import eyed3
import urllib2
import urllib
from urllib import urlencode
import sys 

import os
reload(sys) 
sys.setdefaultencoding('utf8')

music_path = r"E:\music"
lrc_path = r"e:\lrc"

os.remove('nolrc.txt')
os.remove('lrcxml.txt')

the_file = open('lrcxml.txt','a')
nolrc_file = open('nolrc.txt','a')

for root,dirs,files in os.walk(music_path):
  for filepath in files:
    the_path = os.path.join(root,filepath)
    if (the_path.find("mp3") != -1):
      print the_path
      the_music = eyed3.load(the_path)
      the_teg = the_music.tag._getAlbum()
      the_artist = the_music.tag._getArtist()
      the_title = the_music.tag._getTitle()
      # print the_teg
      # print the_title
      # print the_artist
      b = the_title.replace(' ','+')
      # print b
      a = the_artist.replace(' ','+')
      #print urlencode(str(b))
      if isinstance(a,unicode):
        a = a.encode('utf8')
      song_url = "http://box.zhangmen.baidu.com/x?op=12&count=1&title="+b+"$$"+a+"$$$$ "
     
      the_file.write(song_url+'\n')
      page = urllib2.urlopen(song_url).read()
      print page
      theid = 0
      
      lrcid = re.compile('<lrcid>(.*?)</lrcid>',re.S).findall(page)
      have_lrc = True
      if lrcid != []:
        theid = lrcid[0]
        
      else:
        nolrc_file.write(the_title+'\n')
        have_lrc = False
      print theid
      
      
      if have_lrc:
        firstid = int(theid)/100
        lrcurl = "http://box.zhangmen.baidu.com/bdlrc/"+str(firstid)+"/"+theid+".lrc"
        print lrcurl
        lrc = urllib2.urlopen(lrcurl).read()
        if(lrc.find('html')== -1):
          lrcfile = open(lrc_path+"\\"+the_title+".lrc",'w')
          lrcfile.writelines(lrc)
          lrcfile.close()
        else:
          nolrc_file.write(the_title+'\n')
        
the_file.close()
nolrc_file.close()
print "end!"

有用第一步请求所获取到底是xml格式的,所以本来想着解析xml来获取lrcid,但是在实现过程中遇到了各种问题,别的还容易,就在这一块儿浪费的时间最长,纠结未果之后,只能改用正则表达式来获取了。。。

使用python将歌词嵌入歌曲中
以前一直用的是Google Play Music来作为手机的音乐播放器,可是现在谷歌被墙的这么厉害的,从PC上传到Google Play的音乐在手机上面同步下来的话特麻烦,索性放弃之买了大名鼎鼎的Poweramp播放器,开始使用之后瞬间就被Poweramp强大的功能所吸引住了,不愧是安卓端的音乐播放器的王者!唯美的锁屏界面,强大的均衡器功能等等。唯一美中不足的就是歌词.如果要显示歌词的话必须安装第三方软件,或者是把歌词嵌入到音乐中。所以昨天下班之后就开始研究,所幸最后终于搞定了,先上下效果图

使用Python下载歌词并嵌入歌曲文件中的实现代码

可以看到,效果还是很不错的呢。
好了,废话不多说,下面上程序
首先,必须安装eyed3模块,还有,我所有的歌词都在E:\lrc这个路径中的

import threading
import time
import datetime
import re
import os
import eyed3
import sys
reload(sys)
sys.setdefaultencoding('utf8')


def getstr(i):
  if i <10:
    return "0"+str(i)
  else:
    return str(i)

musicpath=r'I:\music'

lrcpath=r'E:\lrc'



def deallrc(str):
  mystr=re.sub(r'\[\d\d:\d\d.\d\d\]','',str)
  mystr.replace('\n','')
  return mystr
  


def checklrcfile(path,timespan):
  file=open(path,'r')
  mylrcstr=''
  #print timespan
  for line in file.readlines(100):
    #errorlog(line)
    if line.find(timespan)>0:
      return deallrc(line)
    else:
      continue
  return ''

    
def getlrcstr(lrc):
  mylrcstr=''
  #print lrc
  for i in range(00,05):
    for j in range(00,59):
      for k in range(00,99):
        timespan=getstr(i)+":"+getstr(j)+"."+getstr(k)
        mylrcstr+=checklrcfile(lrc, timespan) 
      #print timespan
  return mylrcstr


def getlrc(musicname):
  musicname=u''.join(musicname)
  musicname=musicname.encode('gb2312')
  for root,dirs,files in os.walk(lrcpath):
    for filepath in files:
      the_path = os.path.join(root,filepath)
      if (the_path.find(musicname) != -1):
        print the_path
        return the_path

def errorlog(path):
  file=open(r'e:\nolrc.txt','a')
  if path is None:
    path=''
  path=path+'\n'
  file.write(path)
  file.close()

def writetag(themusic,lrcstr):
  music=eyed3.load(themusic)
  lrcstr=lrcstr.decode('utf8')
  lrcstr=u''.join(lrcstr)
  #lrcstr=unicode(lrcstr)
  music.tag.lyrics.set(lrcstr)
  music.tag.save()
  
  


def dealmusic(path):
  print path
  the_music = eyed3.load(path)
  the_teg = the_music.tag._getAlbum()
  the_artist = the_music.tag._getArtist()
  the_title = the_music.tag._getTitle()
  #print the_title
  
  try:
    lrc=getlrc(the_title)
    lrcstr=getlrcstr(lrc)
    writetag(path, lrcstr) 
  except:
    errorlog(path)
   
          

class writelrc(threading.Thread):
  def __init__(self,the_path):
    threading.Thread.__init__(self)
    self.thepath=the_path
  def run(self):
    dealmusic(self.thepath)


if __name__=='__main__':
  count=0
  threads=[]
  for root,dirs,files in os.walk(musicpath):
      for filepath in files:
        the_path = os.path.join(root,filepath)
        if (the_path.find("mp3") != -1):
          count+=1
          threads.append(writelrc(the_path))
          if count%10==0:
            for t in threads:
              t.start()
            for t in threads:
              t.join()
            threads=[]

  

好了,大概就是这样,大家有什么问题可以直接提出来,我会尽快回复的。

Python 相关文章推荐
Python实现发送email的几种常用方法
Aug 18 Python
深入理解Python中的super()方法
Nov 20 Python
深入浅析Python中的yield关键字
Jan 24 Python
Python使用zip合并相邻列表项的方法示例
Mar 17 Python
Python实现的银行系统模拟程序完整案例
Apr 12 Python
Python使用微信itchat接口实现查看自己微信的信息功能详解
Aug 22 Python
python对验证码降噪的实现示例代码
Nov 12 Python
python实现把两个二维array叠加成三维array示例
Nov 29 Python
Django实现图片上传功能步骤解析
Apr 22 Python
Python logging模块写入中文出现乱码
May 21 Python
keras中的卷积层&amp;池化层的用法
May 22 Python
解决python 执行sql语句时所传参数含有单引号的问题
Jun 06 Python
Python设置Socket代理及实现远程摄像头控制的例子
Nov 13 #Python
深入解析Python中的urllib2模块
Nov 13 #Python
Python下的常用下载安装工具pip的安装方法
Nov 13 #Python
Python的Flask框架的简介和安装方法
Nov 13 #Python
Python编程入门之Hello World的三种实现方式
Nov 13 #Python
python编程开发之textwrap文本样式处理技巧
Nov 13 #Python
python编程开发之日期操作实例分析
Nov 13 #Python
You might like
深入理解php的MySQL连接类
2013/06/07 PHP
php常用Output和ptions/Info函数集介绍
2013/06/19 PHP
PHP-Fcgi下PHP的执行时间设置方法
2013/08/02 PHP
PHP数组排序之sort、asort与ksort用法实例
2014/09/08 PHP
php文件上传原理与实现方法详解
2019/12/20 PHP
PHP开发api接口安全验证操作实例详解
2020/03/26 PHP
一些经常会用到的Javascript检测函数
2010/05/31 Javascript
google jQuery 引用文件,jQuery 引用地址集合(jquery 1.2.6至jquery1.5.2)
2011/04/24 Javascript
基于jQuery创建鼠标悬停效果的方法
2015/03/07 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
javascript实现数组内值索引随机化及创建随机数组的方法
2015/08/10 Javascript
基于JavaScript实现百叶窗动画效果不只单纯flas可以实现
2016/02/29 Javascript
详解jQuery lazyload 懒加载
2016/12/19 Javascript
JavaScript多线程运行库Nexus.js详解
2017/12/22 Javascript
javascript、php关键字搜索函数的使用方法
2018/05/29 Javascript
node实现socket链接与GPRS进行通信的方法
2019/05/20 Javascript
vue 实现websocket发送消息并实时接收消息
2019/12/09 Javascript
微信公众号服务器验证Token步骤图解
2019/12/30 Javascript
浅谈JavaScript中this的指向问题
2020/07/28 Javascript
学习python处理python编码问题
2011/03/13 Python
深入Python函数编程的一些特性
2015/04/13 Python
Python批量按比例缩小图片脚本分享
2015/05/21 Python
Python使用numpy产生正态分布随机数的向量或矩阵操作示例
2018/08/22 Python
Python实现注册、登录小程序功能
2018/09/21 Python
Python 多维List创建的问题小结
2019/01/18 Python
python 爬取古诗文存入mysql数据库的方法
2020/01/08 Python
Ranorex通过Python将报告发送到邮箱的方法
2020/01/12 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
2020/04/24 Python
使用Python FastAPI构建Web服务的实现
2020/06/08 Python
HTML5本地存储之Web Storage应用介绍
2013/01/06 HTML / CSS
HTML5地理定位实例
2014/10/15 HTML / CSS
学习新党章思想汇报
2014/01/09 职场文书
《棉鞋里的阳光》教学反思
2014/04/24 职场文书
2014年高数考试作弊检讨书
2014/12/14 职场文书
Python包管理工具pip的15 个使用小技巧
2021/05/17 Python
Apache Hudi数据布局黑科技降低一半查询时间
2022/03/31 Servers