发博文
ypxing

http://blog.chinaunix.net/space.php?uid=7451264

<meta http-equiv="refresh" content="600"> <font color="#003399" style="font-size:10pt"> 学而不思则罔,思而不学则殆 </font> <br> <br> <font color="#003399" style="font-size:10pt"> 见贤思齐焉,见   
个人资料
  • 博客访问:458732
  • 博文数量:98
  • 博客积分:8011
  • 博客等级:中将
  • 关注人气: 1
  • 注册时间:2007-04-03 09:38:56
订阅我的博客
  • 订阅
  • 订阅到鲜果
  • 订阅到抓虾
  • 订阅到Google
字体大小: 博文
分类: Shell

How to script songs lyrics retrieval

英文原文: http://www.linux.com/article.pl?sid=07/03/28/154246

我最近写了一个简单的脚本,用来把一个歌词数据库融合到我的一些音乐处理脚本中.我充分利用了开源软件的一大好处,那就是先找了一个实现该功能的程序,然后看看它源的码,来学习别人是怎么做的.

我是从学习Rhythmbox(一个音乐管理程序)的代码开始的.我发现(这个程序的)作者向一个基于Web的叫做Leo的歌词数据库发了许多简单的URL请求.请求的地址是:
http://api.leoslyrics.com/api_search.php?auth=duane&artist=cake&songtitle=comfort eagle
http://api.leoslyrics.com/api_lyrics.php?auth=duane&hid=VxwOBYpM3iY=

第 一个请求返回了一个XML文件,这个文件里包含了搜索的结果,示例如下.(服务器似乎忽略了授权信息[我用的是"duane"]. 我也没有找到关于这个网站的基于Web的 API文档.我试着以能提交歌词的账号登录该网站,然后向该网站支持的地址发送电子邮件,但仍然没有响应.)

<?xml version="1.0" encoding="UTF-8"?>
<leoslyrics>
 <response code="0">SUCCESS</response>
 <searchResults>
   <result id="120741" hid="VxwOBYpM3iY=" exactMatch="true">
     <title>Comfort Eagle</title>
     <feat/>
     <artist>
       <name>Cake</name>
     </artist>
   </result>
 </searchResults>
</leoslyrics>

从 这个response元素(<response code="0">SUCCESS</response>)来看,这次请求成功了.接下来我比较感兴起的是这个result元素 (<result id="120741" hid="VxwOBYpM3iY=" exactMatch="true">),特别是这个hid属性,它是这条歌词的id. 我把这个hid传到第二个URL中,然后得到下面这个结果:
<?xml version="1.0" encoding="UTF-8"?>
<leoslyrics>
 <response code="0">SUCCESS</response>
 <lyric hid="VxwOBYpM3iY=" id="120741">
   <title>Comfort Eagle</title>
   <feat/>
   <artist>
     <name>Cake</name>
   </artist>
   <albums>
     <album>
       <name>Comfort Eagle</name>
       <imageUrl>http://images.amazon.com/images/P/B00005MCW5.01.MZZZZZZZ.jpg</imageUrl>
     </album>
   </albums>
   <writer/>
   <text>We are building a religion
We are building it bigger
.................
Pendant keychains</text>
 </lyric>
</leoslyrics>

从这结果,我知道我可以提取出text元素 (<text>.../<text>)来得到我的歌词

我 在bash脚本里用wget和xmlstarlet来自动完成这个过程.wget是一个从Internet上以非交互的方式下载文件的小工具.我就是用 wget来请求(上面的)具有正确参数的URL来捕捉的这些XML结果的.Xmlstarlet是一组用来查询和处理XML文档的命令行工具.我用 xmlstarlet来从URL请求的结果中提取相关信息.

为了使这个脚本实用,我给这个脚本提供了一个MP3文件的路径,然后让它从这个文件的ID3标签中提取演唱者和歌名信息,用这些信息再来下载歌词.我用了id3tool,这是一个可以查看和编辑MP3文件的ID3标签的命令行工具.

在脚本的一开始运行完id3tool之后,我用sed来从id3tool的输出中提取演唱者信息,并把它存到一个叫ARTIST的shell变量中.我用类似的方法提取歌名信息.
ARTIST=`id3tool "$1" | sed -ne "s/.*Artist:\(.*\)/\1/p"`

我接着用wget来请求带有(刚才提取的)演唱者和歌名参数的URL. 请求返回的XML结果被存在一个叫做search_results的shell变量中.
search_results=`wget -q "http://api.leoslyrics.com/api_search.php?auth=$AUTH&artist=$ARTIST&songtitle=$SONGTITLE" -O -`

接着,我用xmlstarlet来解析这个XML结果.下面这个例子是执行xmlstarlet的sel命令来解析这个文本的response元素:
result=`echo $search_results | xmlstarlet sel -t -v "/leoslyrics/response/text()"`

最后,我把上面提到的技巧合起来使用(来提取歌词),再用xmlstarlet的unesc命令处理一下(unsec仅仅是用来在文本中恢复所有的转义字符,这样读起来更方便)
echo $lyrics | xmlstarlet sel -t -v "/leoslyrics/lyric/text/text()" | xmlstarlet unesc > "$1.txt"

完整的脚本一次可以下载一首个歌的歌词.如果要下载你的所有歌的歌词,你可以使用带有exec参数的find命令,来在你的所有歌曲上执行这个脚本. 例如,你的歌曲库在/share/music/目录下,你可以执行:
find /share/music/ -iname *.mp3 -exec get_lyrics.sh {} \;

你可以很容易的在你喜欢的语言里,使用同样的URL请求和结果解析技术(只要这种语言可以提取网页并能解析XML).这些技术也可以修改后用到其他支持基于Web APIs的歌词数据库中.

亲,您还没有登录,请[登录][注册]后再进行评论