天天看點

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

最近這段時間老師讓我們學生自己去做個項目,我自己選擇做一個音樂播放器,因為這個比較簡單,上手也比較容易,老師教的知識基本都用得上。

我自己就無聊跑去弄個網絡擷取歌單,當然也隻是歌單,并不能實作播放功能,不過也學到了一些知識。擷取網絡的歌曲名與歌手名,我是這樣弄的,我參考了很多前輩的用法,大多數的前輩們基本都是使用jsoup這個包去解析一些音樂網站,然後再擷取想要的資訊,這裡我對我學到的知識做一下總結:

首先我們需要去導一下jsoup的jar包,在Android Studio中導入的方法:

第一種方法:可以直接在app檔案夾下的build.gradle中的

dependencies{

compile 'org.jsoup:jsoup:1.10.3' //版本看情況

 }

第二種方法:可以直接去https://jsoup.org/download 這個網址下載下傳jsoup的jar包,下載下傳完後,

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上
Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

然後對着這個jar包點選右鍵 找到Add As Library,軟體就會幫你導入這個jar包啦

第三種方法:這種最為友善,可以直接在Android Studio中下載下傳

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

這些準備工作基本都做完了,下面我們就開始進入項目中:

首先我們先把他的布局給弄出來,不弄布局哪裡會顯示哦。。

布局檔案名:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context="com.caijixieshou.NetMusic.MainActivity">

    <ListView

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/net_song_listview"

        />

</LinearLayout>

弄好布局後,我們建立在java檔案夾下建立一個包叫domain,在該包下建立一個Bean類NetSongsResults來封裝歌曲的資訊

public class NetSongsResults {

    private String MusicName;//歌名

    private String Artist;//歌手名

    private String Album;//專輯

    //用系統自帶的Getter和Setter封裝

    public String getMusicName() {

        return MusicName;

    }

    public void setMusicName(String musicName) {

        MusicName = musicName;

    }

    public String getArtist() {

        return Artist;

    }

    public void setArtist(String artist) {

        Artist = artist;

    }

    public String getAlbum() {

        return Album;

    }

    public void setAlbum(String album) {

        Album = album;

    }

    //這裡用系統生成的toString方法為了友善列印資訊

    @Override

    public String toString() {

        return "NetSongsResults{" +

                "MusicName='" + MusicName + '\'' +

                ", Artist='" + Artist + '\'' +

                ", Album='" + Album + '\'' +

                '}';

    }

}

弄好了bean檔案後,我們還在java檔案夾下建立一個工具util包,在該包下建立一個解析類JsoupUtils,該類用來解析音樂網站

public class JsoupUtils {

    private static JsoupUtils instance;

    //這裡用單例的方式,為了友善使用

    public static JsoupUtils getInstance(){

        if (instance == null){

            instance = new JsoupUtils();

        }

        return instance;

    }

    public void getMusic(final String url, final String title,

                         final String artist, final ArrayList<NetSongsResults> datalist,

                         final CallBack mCallBack){

        //因為聯網解析網頁屬于一種耗時操作,是以我們需要在這裡另起一個線程

        new Thread(new Runnable() {

            @Override

            public void run() {

                try {

                    Document doc = Jsoup.connect(url).userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) " +

                            "AppleWebKit/537.36 (KHTML, like G" +

                            "ecko) Chrome/53.0.2785.104 " +

                            "Safari/537.36 Core/1.53.3226.400").timeout(10000).get();

                    Elements titleEls = doc.select(title);

                    Elements artistEls = doc.select(artist);

                    //這裡我們周遊一下我們所擷取的資訊,然後通過bean類封裝資訊再把資訊添加到集合中

                    for (int i = 0;i<titleEls.size();i++){

                        //執行個體化NetSongsResults

                        NetSongsResults netSongsResults = new NetSongsResults();

                        //getAllElements方法為擷取該cssQuery下的所有标簽(我網頁學得不好,我也不知道是不是)

                        Elements title = titleEls.get(i).getAllElements();

                        //這裡用netSongsResults調用set方法封裝資訊

                        netSongsResults.setMusicName(title.get(0).text());

                        Elements artist = artistEls.get(i).getAllElements();

                        netSongsResults.setArtist(artist.get(0).text());

                        //這裡添加專輯名,随便起一個

                        netSongsResults.setAlbum("最新推薦");

                        //最後把netSongsResults添加到集合中

                        datalist.add(netSongsResults);

                    }

                    //判斷如果資料源不為空的時候調用回調接口的Success方法,為空時調用Error方法

                        if (datalist != null){

                            mCallBack.Success(datalist);

                        } else {

                            mCallBack.Error(datalist);

                        }

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }).start();

    }

    //這裡我們定義一個回調接口,判斷是否成功的擷取到了datalist

    public interface CallBack{

        public void Success(ArrayList<NetSongsResults> datalist);

        public void Error(ArrayList<NetSongsResults> datalist);

    }

}

弄好了工具類之後,我們弄一個自定義擴充卡去為了讓ListView顯示資料,ListView中的每一項的布局為:

item_net_song_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical"

    >

    <TextView

        android:id="@+id/item_net_title"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:singleLine="true"

        android:layout_marginLeft="10dp"

        android:layout_marginTop="5dp"

        android:textSize="17sp"

        />

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginTop="10dp"

        android:orientation="horizontal"

        android:layout_marginLeft="10dp"

        android:layout_marginBottom="10dp"

        >

        <TextView

            android:id="@+id/item_net_artist"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:singleLine="true"

            android:text="未知藝術家"

            android:textSize="15sp" />

        <TextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="  -  "

            android:textSize="20sp"

            />

        <TextView

            android:id="@+id/item_net_ablum"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:singleLine="true"

            android:text="未知專輯"

            android:textSize="15sp" />

    </LinearLayout>

</LinearLayout>

弄好了布局之後就開始寫自定義擴充卡了

public class NetSongAdapter extends BaseAdapter {

    private Context context; //上下文

    private ArrayList<NetSongsResults> datalist; //資料源

    private LayoutInflater inflater; //布局填充器

    private NetSongsResults netSongsResults; 

    public NetSongAdapter(Context context, ArrayList<NetSongsResults> datalist) {

        this.context = context;

        this.datalist = datalist;

        this.inflater = LayoutInflater.from(context);

    }

    @Override

    public int getCount() {

        return datalist.size();

    }

    @Override

    public Object getItem(int i) {

        return datalist.get(i);

    }

    @Override

    public long getItemId(int i) {

        return i;

    }

    @Override

    public View getView(int position, View convertView, ViewGroup viewGroup) {

        ViewHolder holder = null;

        if (convertView == null){

            holder = new ViewHolder();

            convertView = inflater.inflate(R.layout.item_net_song_layout,null);

            holder.title = convertView.findViewById(R.id.item_net_title);

            holder.artist = convertView.findViewById(R.id.item_net_artist);

            holder.ablum = convertView.findViewById(R.id.item_net_ablum);

            convertView.setTag(holder);

        } else {

            holder = (ViewHolder) convertView.getTag();

        }

//執行個體化NetSongsResults對象,去接收datalist.get(position);

        netSongsResults = datalist.get(position);

        String artist = netSongsResults.getArtist();

        String ablum = netSongsResults.getAlbum();

        holder.title.setText(netSongsResults.getMusicName());

        if (!TextUtils.isEmpty(artist)){

            holder.artist.setText(artist);

        } else {

            holder.artist.setText("未知藝術家");

        }

        if (!TextUtils.isEmpty(ablum)){

            holder.ablum.setText(ablum);

        }else {

            holder.ablum.setText("未知專輯");

        }

        return convertView;

    }

    class ViewHolder{

        TextView title;

        TextView artist;

        TextView ablum;

    }

}

擴充卡也弄好了,我們就開始去寫MainActivity了

public class MainActivity extends AppCompatActivity {

    private ListView net_song_listview;

    private static final String url = "http://music.baidu.com/search?key=%E8%96%9B%E4%B9%8B%E8%B0%A6";

    private ArrayList<NetSongsResults> datalist;

    private NetSongAdapter netSongAdapter;

    private Handler handler;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        initView();

    }

    private void initView() {

        net_song_listview = (ListView) findViewById(R.id.net_song_listview);

        handler = new Handler(){

            @Override

            public void handleMessage(Message msg) {

                switch (msg.what){

                    case Contents.ConnectSuccess:

                        netSongAdapter = new NetSongAdapter(MainActivity.this,datalist);

                        net_song_listview.setAdapter(netSongAdapter);

                        Toast.makeText(MainActivity.this,"更新完成...",Toast.LENGTH_SHORT).show();

                        break;

                    case Contents.ConnectFail:

                        //msg.what = (int) msg.obj;

                        Toast.makeText(MainActivity.this,"更新失敗...",Toast.LENGTH_SHORT).show();

                        break;

                }

            }

        };

        datalist = new ArrayList<NetSongsResults>();

        JsoupUtils.getInstance().getMusic(url, "span.song-title", "span.author_list",

                datalist, new JsoupUtils.CallBack() {

            @Override

            public void Success(ArrayList<NetSongsResults> datalist) {

                if (datalist != null ){

                    handler.sendEmptyMessage(Contents.ConnectSuccess);

                }else {

                    return;

                }

            }

            @Override

            public void Error(ArrayList<NetSongsResults> datalist) {

                if (datalist == null){

                    handler.sendEmptyMessage(Contents.ConnectFail);

                }

            }

        });

    }

}

這樣就把擷取網絡歌曲資訊的功能寫完了,最後需要在配置檔案AndroidManifest.xml中添加網絡權限

<uses-permission android:name="android.permission.INTERNET" />

實際圖是這樣的:

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

之前也有提到在Elements中的select方法的參數怎麼去用,這裡我也是參考前輩的用法粗略的說一下:

首先打開一個網址:https://try.jsoup.org/

打開網頁後點選Fetch Url,會出現下面的視窗:

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

這時候就會出現這樣:

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

這些都是網頁的解析出來的資料,然後再做以下操作:

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上

這樣我們就講完了,如果我講的有什麼地方不好的還請幫忙指出,因為我也是個初學者,學得也不太好,而且也是第一次寫部落格,希望大家多多支援!

Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上
Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上
Android使用jsoup解析音樂網站擷取歌名與歌手名顯示在ListView上