android中使用JSOUP如何解析网页数据详述

最近使用了Jsoup,感觉还是挺简单,挺方便的,轻而易举地抓取网页源码,分析获取各个标签所需的东西。

这几天在搞一个音乐播放器的小项目,其中使用到了就是使用JSOUP进行页面数据的获取,获取网页的歌曲列表,并对歌曲的链接进行加载,以便实现歌曲下载和歌词的下载。搞好之后,就会跟着写几篇博文,分享给大家。本博文主要说明android中使用jsoup如何进行网页数据的获取。

具体可看下面各个相关例子:

Jsoup下载地址:

http://jsoup.org/download

jsoup开发指南,jsoup中文使用手册,jsoup中文文档:

http://www.open-open.com/jsoup/

中文文档非常好,说明也非常详细,网上面好多都是拷贝这个中文文档发的博文。我刚开始的时候看了,但是一直对于其中的选择器所选择的内容一直不知道如何选择。这个问题好多博文没有说明。

本博文不再说明关于jsoup的用法之类的api了,中文文档说明的很明白了,主要说明如何进行解析网页数据。本博文解析的案例主要是解析网页中的歌曲列表,网页地址是:http://music.baidu.com/top/new/?pst=shouyeTop

网页界面:

这个网页是百度音乐的网页,收录了新歌排行榜,项目中就是对这个网页进行解析获取歌曲列表的。

先上图,android实现的界面如下:

解析网页然后,获取网页数据,加载列表,展示给用户。

下面开始具体实现:

1 歌曲对象类

/**
 * 2015年8月15日 15:51:26
 * 博文地址:http://blog.csdn.net/u010156024
 * 歌曲对象类
 */
public class SearchResult implements Serializable {
    private static final long serialVersionUID = 0X00000001l;
    private String musicName;
    private String url;
    private String artist;
    private String album;

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getMusicName() {
        return musicName;
    }

    public void setMusicName(String musicName) {
        this.musicName = musicName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }
}

上面是一个歌曲对象类,非常简单的javabean。不多说了。

2 使用jsoup进行页面数据解析

/**
 * 2015年8月15日 15:54:43
 * 博文地址:http://blog.csdn.net/u010156024
 * 该类完成功能: 有URL链接解析出推荐的歌曲列表
 */
public class SongsRecommendation {// http://music.baidu.com/top/new/?pst=shouyeTop
    private static final String URL = "http://music.baidu.com"
            + "/top/new/?pst=shouyeTop";
    private static SongsRecommendation sInstance;
    /**
     * 回调接口,传递数据给Activity或者Fragment
     * 非常好用的数据传递方式
     */
    private OnRecommendationListener mListener;

    private ExecutorService mThreadPool;

    public static SongsRecommendation getInstance() {
        if (sInstance == null)
            sInstance = new SongsRecommendation();
        return sInstance;
    }

    private Handler mHandler = new Handler() {
        @SuppressWarnings("unchecked")
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case Constants.SUCCESS:
                if (mListener != null)
                    mListener
                    .onRecommend((ArrayList<SearchResult>) msg.obj);
                break;
            case Constants.FAILED:
                if (mListener != null)
                    mListener.onRecommend(null);
                break;
            }
        }
    };

    @SuppressLint("HandlerLeak")
    private SongsRecommendation() {
        // 创建单线程池
        mThreadPool = Executors.newSingleThreadExecutor();
    }

    /**
     * 设置回调接口OnRecommendationListener类的对象mListener
     *
     * @param l
     * @return
     */
    public SongsRecommendation setListener(OnRecommendationListener l) {
        mListener = l;
        return this;
    }
    /**
     * 真正执行网页解析的方法
     * 线程池中开启新的线程执行解析,解析完成之后发送消息
     * 将结果传递到主线程中
     */
    public void get() {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                ArrayList<SearchResult> result = getMusicList();
                if (result == null) {
                    mHandler.sendEmptyMessage(Constants.FAILED);
                    return;
                }
                mHandler.obtainMessage(Constants.SUCCESS, result)
                        .sendToTarget();
            }
        });
    }

    private ArrayList<SearchResult> getMusicList() {
        try {
            /**
             * 一下方法调用请参考官网
             * 说明:timeout设置请求时间,不宜过短。
             * 时间过短导致异常,无法获取。
             */
            Document doc = Jsoup
                    .connect(URL)
                    .userAgent(
                            "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36"
                                    + " (KHTML, like Gecko) Chrome/42.0.2311.22 Safari/537.36")
                    .timeout(60 * 1000).get();
            //select为选择器,请参考官网说明
            Elements songTitles = doc.select("span.song-title");
            Elements artists = doc.select("span.author_list");
            ArrayList<SearchResult> searchResults = new ArrayList<SearchResult>();

            for (int i = 0; i < songTitles.size(); i++) {
                SearchResult searchResult = new SearchResult();
                Elements urls = songTitles.get(i).getElementsByTag("a");
                searchResult.setUrl(urls.get(0).attr("href"));
                searchResult.setMusicName(urls.get(0).text());

                Elements artistElements = artists.get(i).getElementsByTag("a");
                searchResult.setArtist(artistElements.get(0).text());
                searchResult.setAlbum("最新推荐");
                searchResults.add(searchResult);
            }
            return searchResults;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 回调接口 获取数据之后,通过该接口设置数据传递
     */
    public interface OnRecommendationListener {
        public void onRecommend(ArrayList<SearchResult> results);
    }
}

上面这个类就是实现也对网页数据的解析,解析完成之后,通过handler传递给主线程,主线程中handmessage方法中,通过回调接口,将数据传递给调用该类的activity或者fragment。

一般的博文大部分到此就为止了,因为关键部分都已经给大家说明了。但是我想说的是在使用jsoup进行解析的时候,

//select为选择器,请参考官网说明
            Elements songTitles = doc.select("span.song-title");
            Elements artists = doc.select("span.author_list");
            ArrayList<SearchResult> searchResults = new ArrayList<SearchResult>();

            for (int i = 0; i < songTitles.size(); i++) {
                SearchResult searchResult = new SearchResult();
                Elements urls = songTitles.get(i).getElementsByTag("a");
                searchResult.setUrl(urls.get(0).attr("href"));
                searchResult.setMusicName(urls.get(0).text());

                Elements artistElements = artists.get(i).getElementsByTag("a");
                searchResult.setArtist(artistElements.get(0).text());
                searchResult.setAlbum("最新推荐");
                searchResults.add(searchResult);
            }

这部分代码最为关键,而其中

Elements songTitles = doc.select(“span.song-title”);

Elements artists = doc.select(“span.author_list”);

这两句代码中的span.song-title 、span.author_list怎么选的呢?刚开始的时候真是不理解,现在我就带着大家看看如何进行选择的。如果你读到这里已经明白了,那就不用往下看了。如果不明白,请继续。。。

首先到网页http://music.baidu.com/top/new/?pst=shouyeTop,使用浏览器查看源码,截图:

通过查看源码我们知道,上面所选择的span.song-title、span.author_list都是源码中的。

下面我们再到http://try.jsoup.org/ 网页,进行尝试在线解析,页面截图:

下面输入http://music.baidu.com/top/new/?pst=shouyeTop 在线解析看看解析后的数据:

相信由上面两个图的说明,大家应该明白了代码中是如何进行选择器的选取的。按照官网的说明,选择器非常强大,能够进行综合的选择,大大简化从网页中获取数据的复杂度。

至此,基本完成本博文想要说明的内容,如果有什么错误,请大家不吝赐教。如果觉得还可以,请留个言,给个赞呗~~ ^_^谢谢~【握手】

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 22:53:35

android中使用JSOUP如何解析网页数据详述的相关文章

Jsoup登录解析网页信息

今天解析网页的时候,遇到必须登录后才能够访问的问题,在网上搜索了一些资料,反正有人做出来了,不过是使用HttpClient+Jsoup来实现的,我不清楚他们使用什么版本的Jsoup,地址:  HttpClient模拟登陆人人网,并且爬取日志内容(一),http://bbs.csdn.net/topics/390269063,查看现在的Jsoup API,可以直接模拟登陆,获取服务器返回的信息. 我这里是使用水木社区做Demo,其中下面的id和passwd分别是提交form表单中用户名和密码的

使用java开源工具httpClient及jsoup抓取解析网页数据

今天做项目的时候遇到这样一个需求,需要在网页上展示今日黄历信息,数据格式如下 公历时间:2016年04月11日 星期一 农历时间:猴年三月初五 天干地支:丙申年 壬辰月 癸亥日 宜:求子 祈福 开光 祭祀 安床 忌:玉堂(黄道)危日,忌出行 主要包括公历/农历日期,以及忌宜信息的等.但是手里并没有现成的数据可供使用,怎么办呢? 革命前辈曾经说过,没有枪,没有炮,敌(wang)人(luo)给我们造!网络上有很多现成的在线 万年历应用可供使用,虽然没有现成接口,但是我们可以伸出手来,自己去拿.也就是

Android之旅十四 android中的xml文件解析

在我们做有关android项目的时候,肯定会涉及到对xml文件的解析操作.以下给大家介绍一下xml文件的解析.包括DOM.SAX.Pull以及曾经我们用到的DOM4J和JDOM: 要解析的XML文件:person.xml <? xml version="1.0" encoding="UTF-8"? > <persons> <person id="001"> <name>zhangsan</na

Android中复用问题哲理性解析

Android中列表的复用机制提高了APP的运行效率,但随之而来的复用的问题总是让程序员们头痛,一个 bug找头天也找不到.我就把自己解决这方面的经验贡献出来供大家参考: 问题1:什么是复用 复用其实指的是复用View,而绑定View的数据是变化的. 问题2:复用出现的场景 在Adapter中,如果绑定View的数据的时候如果有if判断,往往很多人忘记了加else,这是大多数复用问题出现的根源. 实际场景:     比如每个item可能有或没有图片picarrList,之前我只加了if判断,如果

Google中Gson的使用解析json数据-------学习篇

之前写过一篇Gson解析json数据的基本应用,这里不多说,直接上例子. 有兴趣的可以先阅读下之前那篇,这里附上链接: http://www.cnblogs.com/Ant-soldier/p/6322456.html // json跟set集合之间的转换        String str = "[{'name':'zhangsan','age':20},{'name':'lisi','age':33}]";        Gson gson = new Gson();      

android中SharedPreferences和PreferenceActivity的存取数据

本文主要介绍SharedPreferences和PreferenceActivity的基础知识和用法. 主要资料来源于网络,包括但不限于: <Android之PreferenceActivity>--http://www.cnblogs.com/wservices/archive/2010/07/08/1773449.html <在Android中Preferences数据存储的使用> <Android的设置界面及Preference使用> <OnPreferen

修改Android中strings.xml文件, 动态改变数据

有些朋友可能会动态的修改Android中strings.xml文件中的值,在这里给大家推荐一种简单的方法.strings.xml中节点是支持占位符的,如下所示: <string name="data">整数型:%1$d,浮点型:%2$.2f,字符串:%3$s</string> 其中%后面是占位符的位置,从1开始, $ 后面是填充数据的类型         %d:表示整数型:         %f :表示浮点型,其中f前面的.2 表示小数的位数         %

android中SurfaceView组件使用解析

SurfaceView组件可以实现高效率的绘制二维图或者显示图像,在游戏开发中经常用到.在android中,已经提供了SurfaceView组件.使用时,一般是通过继承的方法实现自定义surfaceView,也可以在MainActivity中通过接口surfaceHolder.callback接口实现,这里介绍通过接口实现surfaceView绘图,当然,绘图可以是静态图(在指定区域只绘制一次),也可以是动态图(指定区域-->绘制-->再循环). SurfaceView组件的使用流程:通过fi

Android Jsoup 爬取网页数据

一不小心一个月又过去了,其实最近还是小忙小忙的,废话不多说,直接进入今天的主题吧. Jsoup – Java HTML Parser, with best of DOM, CSS, and jquery.,看这个介绍就知道,这个就是方便咱们 Java 和Android 来解析 HTML 的. HTML 标签 要去爬别人的 HTML 标签的话,首先你肯定得有一定的 HTML 的基础知识吧.比如说常用的标签,标签的相关属性,这个就不多说了,有相关问题都可以在 www.w3school.com.cn