阳光男孩

Never give up!

Entries for 二月, 2012

Java程序自动下载谷歌音乐歌词

1顶一下  近期写了一个android音乐播放器,但是苦于找不到可以自动下载歌词的网站。网上搜的那个已经不能用了。这时候想起可以调用百度或者谷歌的接口来搜索歌词,由于谷歌刚刚推出了谷歌音乐,于是我就想着去尝试下。    进入谷歌音乐的主页,然后随便输了首歌去搜索,跳转至歌曲搜索。发现真的有歌词,可惜歌词不是嵌套在网页里的,并且打开歌词网页的地址里包含的是歌词的id,这可这么半呢...[阅读全文]

1
顶一下

  近期写了一个android音乐播放器,但是苦于找不到可以自动下载歌词的网站。网上搜的那个已经不能用了。这时候想起可以调用百度或者谷歌的接口来搜索歌词,由于谷歌刚刚推出了谷歌音乐,于是我就想着去尝试下。

   进入谷歌音乐的主页,然后随便输了首歌去搜索,跳转至歌曲搜索。发现真的有歌词,可惜歌词不是嵌套在网页里的,并且打开歌词网页的地址里包含的是歌词的id,这可这么半呢?

   于是我就去搜索页面寻找歌曲的id,果然在html源代码中找到了歌曲的id,然后我就用这个id拼接在歌词网址的字符串中,最后顺利地进入了歌词页面。

   不过歌词页面中的信息很少,连歌词都是从别的地方读取过来的,html源代码中也没有歌词相应的地址。还好,在页面的框架信息中我看到了歌词的地址,在浏览器输入后就可以直接下载,并且下载后的文件就是歌曲的歌词,不含其他信息。

    这样就有思路了:

    1.接收参数为歌曲名和歌手(这样可以准确的定位歌词文件),然后把参数拼接在查询字符串后面,进行歌词页面的查询。

    2.获取歌词页面的html源代码并进行解析,获取歌曲的id

    3.将歌曲的id拼接在歌词框架页面地址的后面,获取歌词框架页面的html源代码

    4.解析框架页面的源代码,获取歌词下载地址。

    5.下载歌词并保存至文件。

需要注意的是:

1.谷歌音乐的歌曲、歌手都不是很多,有些歌曲可能搜索不到歌词,甚至谷歌就没有收录这些歌曲。

2.谷歌服务器不稳定,歌词可能会下载失败,原因大家都懂得。

3.下载的歌词默认放在工程目录下,可以自行修改歌词位置。

4.谷歌音乐页面编码都是UTF-8的,不需要考虑乱码的问题。

PS:本程序仅仅是抛砖引玉,具体怎么使用就看大家的了。

下面上代码:

工具类

 

[java]

<span style=”font-family:FangSong_GB2312;”><span style=”font-size: 14px;”></span></span><pre name=”code” class=”java”>package com.zyc.download_lrc;
/**
 * Get lrc from google music
 * Version 1.00
 * @author zyc
 * 2012.2.2
 */

/*
 * Step:
 * 1.Input music’s name and artist,use google music search engine
 * The url like ”http://www.google.cn/music/search?q=name+artist”
 * 2.Get music id,the id is starts with ”http://g.top100.cn/16667639/html/lyrics.html?id”
 * and id is after
 * 3.Use id to get lrc framework html,find download lrc url
 * 4.download lrc
 * 5.write lrc to file
 *
 * NOTICE:google work may abnormal,you known
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;

public class DownloadGoogleLrcTool {
    /*music info start,but can’t get id from this,because the music has no lrc*/
    private final static String ID_HEAD_FLAG = ”<!–freemusic”;
    /*google music engine search head*/
    private final static String SEARCH_ENGINE_HEAD = ”http://www.google.cn/music/search?q=”;
    /*google music lrc by id head*/
    private final static String SEARCH_ID_URL_HEAD = ”http://www.google.cn/music/top100/lyrics?id=”;
    /*google music id flag*/
    private final static String SEARCH_ID_FLAG = ”http://g.top100.cn/16667639/html/lyrics.html?id”;
    /*google music download url flag*/
    private final static String SEARCH_LRC_DOWNLOAD_URL_FLAG = ”http://lyric.top100.cn/”;
    /*”%3D” means ”=”*/
    private final static String SEARCH_HTML_EQUAL = ”%3D”;
    private final static String END_FLAG = ”\\”;
    private final static String LRC_SUFFIX = ”.lrc”;
    private final static String LINE_END = ”\n”;
    /*google music can’t connect return code”*/
    private final static String GOOGLE_SB_RETURN_CODE = ”502″;
    /*error message,you know”*/
    private final static String GOOGLE_SB_MESSAGE = ”google抽风中…你懂的\n请稍后再试”;
    private final static String SPACE = ” ”;
    /*”%20″ means ” ”*/
    private final static String HTML_SPACE = ”%20″;
    private final static String HTML_URL_HEAD = ”http://”;
    /*id is letter and number”*/
    private final static String ID_MATCH = ”^[A-Za-z0-9]+{1}quot;;
    /*download message*/
    private final static String CANNOT_FIND_LEC_MESSAGE = ”无法找到歌词”;
    private final static String FAIL_MESSAGE = ”下载歌曲 %s-%s 歌词 失败!\n原因:”;
    private final static String SUCCESS_MESSAGE = ”下载歌曲 %s-%s 歌词 成功!\n歌词位置: %s\n”;
    private final static String DOWNLOADING_MESSAGE = ”正在下载歌曲 %s-%s 歌词…\n”;
    /*time out message*/
    private final static String DOWNLOADING_CONNECT_TIME_OUT = ”connect timed out”;
    private final static String DOWNLOADING_CONNECT_TIME_OUT_MESSAGE = ”连接超时,请检查网络配置”;
    private final static String DOWNLOADING_UNKNOWN_MESSAGE = ”未知”;
    /*set timeout = 5s*/
    private final static long CONNECT_TIME_OUT = 5000;
    /*set http proxy,if don’t use http proxy,set it false*/
    private final static boolean USE_HTTP_PROXY = true;
    private final static String FAIL_WRITE_FILE_MESSAGE = ”写入文件失败!”;

    public static void downloadLrcFromGoogle(String name,String artist){
        try {
            System.out.printf(DOWNLOADING_MESSAGE,name,artist);
            /*get lrc*/
            String lrc = downloadLrc(name,artist);
            if(lrc != null){
                /*write lrc to file*/
                String fileName = name + LRC_SUFFIX;
                File file = new File(fileName);
                writeToFile(file, lrc);
                System.out.printf(SUCCESS_MESSAGE, name,artist,file.getAbsoluteFile());
            }
            else
                System.out.println(CANNOT_FIND_LEC_MESSAGE);
        } catch (Exception e) {
            System.out.printf(FAIL_MESSAGE, name,artist);
            if(e.getMessage().contains(GOOGLE_SB_RETURN_CODE))
                System.out.println(GOOGLE_SB_MESSAGE);
            else if(e.getMessage().contains(DOWNLOADING_CONNECT_TIME_OUT)){
                System.out.println(DOWNLOADING_CONNECT_TIME_OUT_MESSAGE);
            }
            else {
                System.out.println(DOWNLOADING_UNKNOWN_MESSAGE);
            }
            //e.printStackTrace();
        }
    }

    private static void init(){
        System.setProperty(“sun.net.client.defaultConnectTimeout”, String.valueOf(CONNECT_TIME_OUT));
        if(USE_HTTP_PROXY){
            //add http proxy setting here

        }
    }

    private static String downloadLrc(String name,String artist) throws IOException,SocketTimeoutException{
        init();
        /*replace ” ” to ”%2d”*/
        name = name.replaceAll(SPACE, HTML_SPACE);
        artist = artist.replaceAll(SPACE, HTML_SPACE);
        String id = getSongId(name, artist);
        /*can’t find id return null”*/
        if(id == null || !id.matches(ID_MATCH)){
            return null;
        }
        String path = getLrcDownloadUrl(id);
        String lrc = null;
        /*if path isn’t start with ”http”//” ignore*/
        if(path.startsWith(HTML_URL_HEAD))
            lrc = doDownloadLrc(path);
        return lrc;
    }

    private static String getSongId(String name,String artist) throws IOException{
        String source = readHtml(SEARCH_ENGINE_HEAD + name + ”+” + artist);
        name = name.replaceAll(HTML_SPACE, SPACE);
        String match01 = ”\”><b>” + name + ”</b>”;
        String match02 = null;
        if(name.contains(SPACE)){
            /*set first letter upper*/
            String[] array = name.split(SPACE);
            for (int i = 0;i < array.length;i++) {
                char firstChar = array[i].charAt(0);
                if(firstChar >= ’a' && firstChar <= ’z'){
                    array[i] = array[i].replace(firstChar, (char) (firstChar - 32));//set upper
                }
            }
            String newName = ”";
            for (int i = 0;i < array.length;i++) {
                if(i < array.length - 1)
                    newName += array[i] + SPACE;
                else
                    newName += array[i];
            }
            match02 = ”\”><b>” + newName + ”</b>”;
        }
        if(!source.contains(match01) && match02 != null && !source.contains(match02)){
            /*may other music return*/
            return null;
        }
        int first = source.indexOf(ID_HEAD_FLAG);
        if(first == -1){
            /*no music id*/
            return null;
        }
        int last = source.indexOf(ID_HEAD_FLAG,first + ID_HEAD_FLAG.length());
        if(last != -1){
            /*ignore only a music id,if have some choose first one*/
            source = source.substring(first,last);
        }
        /*find id*/
        int start = source.indexOf(SEARCH_ID_FLAG);
        int mid = source.indexOf(SEARCH_HTML_EQUAL, start);
        int end = source.indexOf(END_FLAG,mid);
        if(start == -1 || mid == -1 || end == -1){
            //can’t find id
            return null;
        }
        String id = source.substring(mid + HTML_SPACE.length(), end);
        return id;
    }

    private static String getLrcDownloadUrl(String id) throws IOException{
        /*set music lrc html url with id*/
        String source = readHtml(SEARCH_ID_URL_HEAD + id);
        int start = source.indexOf(SEARCH_LRC_DOWNLOAD_URL_FLAG);
        int end = source.indexOf(LRC_SUFFIX,start);
        String urlString = source.substring(start, end + LRC_SUFFIX.length());
        return urlString;
    }

    private static String doDownloadLrc(String path) throws IOException{
        /*download lrc*/
        return readHtml(path);
    }

    private static String readHtml(String urlPath) throws IOException{
        /*use google music search engine*/
        URL url = new URL(urlPath);
        /*connect and get html */
        URLConnection conn = url.openConnection();
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line = null;
        StringBuilder stringBuilder = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line + LINE_END);
        }
        return stringBuilder.toString();
    }

    private static void writeToFile(File file,String buffer) throws IOException{
        /*write to file,file name is music’s name + ”.lrc”*/
        FileWriter writer = new FileWriter(file, false);
        try {
            writer.write(buffer);
        } catch (Exception e) {
            System.out.println(FAIL_WRITE_FILE_MESSAGE);
        }finally{
            writer.close();
        }
    }
}

测试类

 

[java]

<span style=”font-family:FangSong_GB2312;”><span style=”font-size: 14px;”></span></span><pre name=”code” class=”java”>package com.zyc.download_lrc;

public class DownloadTest {

    public static void main(String[] args) {
        //only for test
        String name = ”决战斗室”;
        String artist = ”潘玮柏”;
        downloadMusicLrc(name, artist);
    }

    static void downloadMusicLrc(String name,String artist){
        DownloadGoogleLrcTool.downloadLrcFromGoogle(name, artist);
    }

}

测试结果:

 

正在下载歌曲 决战斗室-潘玮柏 歌词…
下载歌曲 决战斗室-潘玮柏 歌词 成功!
歌词位置: /project/DownLoadLrc/决战斗室.lrc

歌词如下:

[ti:决战斗室]
[ar:潘玮柏]
[al:高手]
[00:05.00]
[01:20.44][00:16.69]克制不住 心跳加速
[01:22.27][00:18.67]太兴奋追求战斗我才满足
[01:24.25][00:20.47]角落处 全神贯注
[01:26.25][00:22.57]眼神冰冷像只危险老虎
[01:28.23][00:24.58]拳头蹦带 无法束缚
[01:30.25][00:26.55]脉膊跳动的强度快忍不住
[01:32.22][00:28.51]灯在闪 人群在喊
[01:34.19][00:30.48]抬起头我完全不屑一顾
[01:36.21][00:32.60]Noboby gonna stop me
[01:38.21][00:34.57]沉默中 聆听自己
[01:40.07][00:36.54]Noboby gonna front me
[01:42.23][00:38.51]相信自己 绝不会逃避
[01:44.25][00:40.55]Noboby gonna touch me
[01:46.19][00:42.48]呐喊声全场淹没
[01:48.12][00:44.41]推开门 走出自我
[01:50.06][00:46.22]This is my life my soul
[02:44.39][02:28.08][01:52.15][00:48.47]紧握灵魂的手
[02:45.75][02:29.93][01:54.03][00:50.35]最后一刻战斗
[02:47.86][02:31.96][01:56.10][00:52.38]黑暗恐惧之中
[02:50.61][02:33.71][01:57.84][00:54.19]决战斗室只剩你我
[02:51.86][02:35.86][02:00.09][00:56.38]倒数的计时钟
[02:53.77][02:37.90][02:02.00][00:58.30]胜利才终结转动
[02:57.37][02:41.51][02:05.59][01:01.84]我闭上眼我站在斗室中
[02:59.29][02:43.35][02:07.50][01:03.94]只剩下Oh oh

然后就可以放进手机同步播放了!

搞定!!!

Leave a Comment

JDK 8(Lambda版)开发者预览版发布

1顶一下之前有报道称,Java 8中将支持Lambda语法,在JDK 8开发者预览版发布之后,Java社区的Lambda项目又在JDK中添加了Lambda功能。 Lambda项目旨在通过在Java语言中添加闭包(closures)及相关功能,来支持在多核心环境下编程。 该开发者预览版基于最新的OpenJDK 7源码库,使用了一些尚未在JDK8中使用的源码文件,届时如果这些源码文件可用,将会被整合进JDK8中。 需要注意的是,此次发布的预览...[阅读全文]

1
顶一下

之前有报道称,Java 8中将支持Lambda语法,在JDK 8开发者预览版发布之后,Java社区的Lambda项目又在JDK中添加了Lambda功能。

Lambda项目旨在通过在Java语言中添加闭包(closures)及相关功能,来支持在多核心环境下编程。

该开发者预览版基于最新的OpenJDK 7源码库,使用了一些尚未在JDK8中使用的源码文件,届时如果这些源码文件可用,将会被整合进JDK8中。

需要注意的是,此次发布的预览版意味着允许开发者试验Lambda功能,而不需要他们自己编译相关功能的包。该版本并非官方正式版,仅用于开发者测试交流。

下载:

JavaSE 8 Developer Preview

JavaSE 8 Developer Preview with Lambda Support

Leave a Comment

JAVA可移植性广泛应用

0顶一下JAVA可移植性广泛应用。软件可移植性指与软件从某一环境转移到另一环境下的难易程度。为获得较高的可移植性,在设计过程中常采用通用的程序设计语言和运行支撑环境。尽量不用与系统的底层相关性强的语言。下面介绍JAVA的可移植性。 一、JAVA作为一种编程语言:源代码可移植性 作为一种编程语言,JAVA提供了一种最简单同时也是人们最熟悉的可移植性–源代码移植。这意味着任意一个JAVA程序...[阅读全文]

0
顶一下

JAVA可移植性广泛应用。软件可移植性指与软件从某一环境转移到另一环境下的难易程度。为获得较高的可移植性,在设计过程中常采用通用的程序设计语言和运行支撑环境。尽量不用与系统的底层相关性强的语言。下面介绍JAVA的可移植性。

一、JAVA作为一种编程语言:源代码可移植性

作为一种编程语言,JAVA提供了一种最简单同时也是人们最熟悉的可移植性–源代码移植。这意味着任意一个JAVA程序,不论它运行在何种CPU、操作系统或JAVA编译器上,都将产生同样的结果。这并不是一个新的概念。人们使用C、C++也可以产生同样的效果。

但是使用C或C++编程人们可以有太多的选择,在许多细节上它都没有严格定义,如:未初始化变量的值、对已释放的内存的存取、浮点运算的尾数值等等。所以除非你一开始就严格按照系统无关的概念来进行设计,否则这种可移植性只能是一种理论上的设想而不能形成实践。

总之,尽管C和C++有严密的语法定义,它们的语意(symantics)定义还不是标准的。这种语意上的不统一使得同一段程序在不同的系统环境下会产生不同的结果。有时即使系统情况完全相同而仅仅由于编译器的设置不同也会产生令人意想不到的结果。而JAVA就不同了。它定义了严密的语意结构,而使编译器不承担这方面的工作。

另外,JAVA对程序的行为的定义也比C和C++严格,如:它提供了内存自动回收功能(GarbageCollection),使程序不能访问越界内存;它对未初始化的变量提供确定值等等。它的这些特性能够减小在不同平台上运行的JAVA程序之间的差异,也使得JAVA具有即使没有JAVA虚拟机的存在的情况下比C和C++更好的平台无关性。

然而,这些特点也有它不利的一面。JAVA设想运行于具有32位字节长度且每字节为8位的计算机上,这就使得那些8位字长的计算机和一些巨型机不能有效的运行JAVA程序。在这样的平台上就只能运行那些可移植的C和C++程序了。

二、JAVA作为一个虚拟机:CPU可移植性

大多数编译器产生的目标代码只能运行在一种CPU上(如Intel的x86系列),即使那些能支持多种CPU的编译器也不能同时产生适合多种CPU的目标代码。如果你需要在三种CPU(如x86、SPARC和MIPS)上运行同一程序,就必须编译三次。

但JAVA编译器就不同了。JAVA编译器产生的目标代码(J-Code)是针对一种并不存在的CPU–JAVA虚拟机(JAVAVirtualMachine),而不是某一实际的CPU.JAVA虚拟机能掩盖不同CPU之间的差别,使J-Code能运行于任何具有JAVA虚拟机的机器上。

虚拟机的概念并不是JAVA所特有的:加州大学几年前就提出了PASCAL虚拟机的概念;广泛用于Unix服务器的Perl脚本也是产生与机器无关的中间代码用于执行。但针对Internet应用而设计的JAVA虚拟机的特别之处在于它能产生安全的不受病毒威胁的目标代码。正是由于Internet对安全特性的特别要求才使得JVM能够迅速被人们接受。当今主流的操作系统如OS/2、MacOS、Windows95/NT都已经或很快提供对J-Code的支持。

作为一种虚拟的CPU,JAVA虚拟机对于源代码(SourceCode)来说是独立的。我们不仅可以用JAVA语言来生成J-Code,也可以用Ada95来生成。事实上,已经有了针对若干种源代码的J-Code编译器,包括Basic、Lisp和Forth.源代码一经转换成J-Code以后,JAVA虚拟机就能够执行而不区分它是由哪种源代码生成的。这样做的结果就是CPU可移植性。
将源程序编译为J-Code的好处在于可运行于各种机器上,而缺点是它不如本机代码运行的速度快。

三、JAVA作为一种虚拟的操作系统(OS)和图形用户界面(GUI):操作系统可移植性

即使经过重新编译,大多数的用C和C++编写的Windows程序也不能在Unix或Macintosh系统上运行。这是为什么呢?因为程序员在编写Windows程序时使用了大量的WindowsAPI和中断调用,而Windows程序对系统功能的调用与Unix和Macintosh程序有很大的差别,所以除非将全套WindowsAPI移植到其它操作系统上,否则重编译的程序仍不能运行。

JAVA采用了提供一套与平台无关的库函数(包括AWT、UTIL、LANG等等)的方法来解决这个问题。就象JVM提供了一个虚拟的CPU一样,JAVA库函数提供了一个虚拟的GUI环境。JAVA程序仅对JAVA库函数提出调用,而库函数对操作系统功能的调用由各不同的虚拟机来完成。

JAVA也在它的OS/GUI库中使用了一种“罕见名称符”(least-commom-denominator)来提供对某种特定操作系统的功能调用,即此功能只在特定环境下生效而在其它操作系统下则被忽略。

这样做的好处在于可以针对某操作系统生成拥有人们熟悉的界面的应用程序而同时此程序又能在其它系统下运行。缺点则是系统中的某些功能调用有很强的依赖性因而在JAVA的虚拟OS/API中难以实现。遇到这种情况,程序员就只能写不可移植的程序了。

总之,JAVA在可移植性方面的特点使它在Internet上具有广泛的应用前景。同时它本身具有的防病毒的能力也使它在需要高可靠性的应用中占有一席之地。

Comments (1)

二级经验心得:菜鸟入门Java语言学习的要点

0顶一下一、掌握静态方法和属性          静态方法和属性用于描述某一类对象群体的特征,而不是单个对象的特征。Java中大量应用了静态方法和属性,这是一个通常的技巧。但是这种技巧在很多语言中不被频繁地使用。理解静态方法和属性对于理解类与对象的关系是十分有帮助的,在大量的Java规范中,静态方法和属性被频繁使用。因此学习者应该理解静态方法和属性。Java在方法和属性的调用上是...[阅读全文]

0
顶一下

一、掌握静态方法和属性

         静态方法和属性用于描述某一类对象群体的特征,而不是单个对象的特征。Java中大量应用了静态方法和属性,这是一个通常的技巧。但是这种技巧在很多语言中不被频繁地使用。理解静态方法和属性对于理解类与对象的关系是十分有帮助的,在大量的Java规范中,静态方法和属性被频繁使用。因此学习者应该理解静态方法和属性。Java在方法和属性的调用上是一致的,区别只表现在声明的时候,这和c++是不同的。

二、重视接口

       在面向对象早期的应用中大量使用了类继承。随着软件工程理论的不断发展,人们开始意识到了继承的众多缺点,开始努力用聚合代替继承。软件工程解决扩展性的重要原则就是抽象描述,直接使用的工具就是接口。接口近年来逐渐成为Java编程方法的核心。另一方面,就应用而言,大部分开发是建立在规范基础之上的,不需要自己建立复杂的继承关系和庞大的类。因此读懂规范和用好规范已经成为应用程序开发人员的首要任务,Java各项规范的主要描述手段就是接口。

三、学好集合框架

        Java描述复杂数据结构的主要方式是集合框架。Java没有指针,而是通过强大的集合框架描述数组、对象数组等复杂的数据结构。学好这些数据结构的描述方法对于应用程序编写,特别是涉及到服务器方、3层结构编程至关重要。程序员在这个时候不能再用诸如数据库结果集之类的结构描述数据了。
由于很多语言没有这么强大的集合框架体系,很多初学者不知所措,更不知道拿来做什么用,因此应该引起足够的重视。

四、例外捕捉

        Java对例外捕捉的强调是空前的,它强迫程序员用显著的与逻辑方法完全不同的方式描述例外捕捉,对于程序描述的完整性和严谨性有很大的意义。c++也有类似的机制,但是我们看到很多c++程序员并不习惯使用这些机制。
Java的初学者应该充分学习好这种例外捕捉机制,养成良好的编程习惯。

五、多线程需要理解机理

        很多Java程序员热衷于多线程程序编写,认为是对逻辑能力的挑战。其实在大量应用中根本就不需要编写多线程程序,或者说大多数编写应用程序的程序员不会去写多线程程序。这是因为多线程机制都内置到基础平台当中了。
程序员应该了解的是多线程原理和多线程安全,这对于今后准确地把握程序是至关重要的。
例如JSP中编写到不同的位置对于多个用户环境的安全影响完全不同,又如著名的Super Servlet是每一个访问作为一个进程,但是每一个页面是一个线程,和Servlet正好相反,对程序的性能和安全的影响有天壤之别。

六、了解网络编程

        Java号称是最强的网络编程语言,但是大多数应用程序开发人员是从来不会自己开发什么底层的网络程序的。
需要做只是了解原理就够了。网络机制的实现是靠平台实现的,除非自己开发平台,否则是不需要知道socket怎么实现,怎么监听访问的。因此在这方面花太多的功夫就偏离了“将来的应用开发是在成熟的平台上展开,而不是自己从底层开发平台”这一假设。

Leave a Comment