Android开发Android技术知识Android知识

Android 使用 jsoup 解析 html

2017-06-17  本文已影响2758人  SheHuan

一、什么是jsoup

jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。——摘自百度百科

1、官方文档:

jsoup Cookbook(中文版)jsoup cookbook(英文版),总有一个版本适合你。

2、能做什么:

由于工作或自己的需要,我们可能要获得某些特定网页的数据,如果没有后台提供也没有开放的Api接口,这时就可以用jsoup自己抓取数据以解决没有数据的问题。

二、使用

1、导入

如果你使用Android Studio的话,首先在Gradle中引入jsoup,这是目前最新的版本

compile 'org.jsoup:jsoup:1.10.3'

其它引入方式见官方文档https://jsoup.org/download

2、选择你需要抓取数据的目标网站,分析目标数据

百度彩票目前已经停止运营了,可以使用 http://tubiao.17mcp.com/Ssq/Haoma.aspx?page=1 来学习

这里我以抓取百度彩票的双色球历史开奖结果为例,用Chrome打开目标网页,进入开发者工具(快捷键 Ctrl + Shift + I),找到要抓取的数据在网页源码的大概位置:

图1
可以看到双色球的开奖结果在一个class="historyOpt"table中。注意观察table中包含了theadtbody,如果你了解HTML中table元素的用法,可能已经猜到了开奖结果数据就在tbody中:
图2
展开tbody标签后,其中的tr就是表格中的一行数据,td代表一个单元格。开奖日期、开奖期数、开奖结果都包含在一个td,其中的开奖结果又嵌套在了另一个table中。
3、解析数据

分析完了数据的基本结构,接下来主角jsoup就该登场解析html了。这里我们使用jsoup的使用选择器语法来查找元素功能,如果了解选择器相关概念的话做起来会容易些。关于jsoup选择器语法可以看这里:http://www.open-open.com/jsoup/selector-syntax.htm
解析数据前,总要先拿到网页源码数据吧,这个jsoup可以轻松帮我实现,并且可以直接得到Document对象:

Document doc = Jsoup.connect(URL).get();

ps:当然你也可以使用okhttp,或者retrofit等其它网络框架。

由于改操作设计网络请求,所以需要在子线程进行哦,有了Document,就可以进行解析工作了:

private List<LotteryData> parseHtml(Document document) {
        Elements elements = document.select("table[class=historylist] > tbody > tr");
        List<LotteryData> list = new ArrayList<>();
        LotteryData data;
        for (Element element : elements) {
            data = new LotteryData();
            data.setNum(element.select("td > a").text());//开奖期数
            data.setDate(element.select("td").get(1).text());//开奖日期
            Elements ems = element.select("td[class=balls] em");//开奖结果
            StringBuilder sb = new StringBuilder();
            for (Element em : ems) {
                sb.append(em.text());
            }
            data.setBalls(sb.toString());
            list.add(data);
        }

        return list;
    }

首先通过Elements elements = document.select("table[class=historylist] > tbody > tr");使用组合选择器,得到了当前页面classhistorylisttable的直接子元素tbody的所有直接子元素tr,也就是当前页面table中的所有行数据,elements是一个ArrayList<Element>类型的集合。

接下来遍历elements,解析每一行数据,我们知道一个element对象对应tr,可以代表一行数据,我们先拿开奖期数,注意观察图2,开奖期数包含在tr行的第一个td单元格中的a标签,所以我们可以这样写:

element.select("td > a").text()

这样就拿到了开奖期数,如图中的2017069。
同样开奖时间是在tr行的第二个td单元格中,获取方式如下:

element.select("td").get(1).text()

至于开奖结果,在tr行中的classballstd单元格中,并用一个子table存储,所以只要得到子table中所有em元素就可以了:

  Elements ems = element.select("td[class=balls] em");

然后再遍历ems,就可以拿到开奖结果了

 for (Element em : ems) {
                sb.append(em.text());
            }

到这里html就解析完成了。在parseHtml()返回了一个List,可以方便列表显示。

4、展示数据

原网站可以按照开始、结束日期的方式来查询开奖结果,所以我们在demo中采用了分页的形式来加载数据,每一页显示30天的开奖数据,所以就要根据页码计算每一页数据对应的开始日期和结束日期,例如第一页[2017-05-18,2017-06-17]、第二页[2017-04-17,2017-05-17] ......,然后拼接到URL后面,一个完整的请求URL是这样的:http://baidu.lecai.com/lottery/draw/list/50?type=range_date&start=2017-05-18&end=2017-06-17
至于如何根据页码计算日期,还是很简单的,可以参考源码。

到这里我们的流程就分析完了,大致从请求到解析再到展示的代码如下:

private void fetchData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Document doc = null;
                try {
                    String[] date = getDate(PAGE_NUM);
                    //拼接URL
                    URL = URL + "&start=" + date[0] + "&end=" + date[1];
                    //请求
                    doc = Jsoup.connect(URL).get();
                    //解析
                    final List<LotteryData> datas = parseHtml(doc);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //更新列表
                            parseDataFinish(datas);
                        }
                    });

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

说了这么多,总要有个效果图吧:

图3

三、小结

用jsoup解析html还是比较简单的,虽然只是它的一小部分功能,用处还是蛮大的,对于不同的网页最大的差别就在分析出如何根据选择器查找元素。但是如果原网页修改了相关代码,可能就会影响数据抓取了,你就需要及时修改你的解析代码了。文中表达有误的地方还请指正,最后希望对你有所帮助吧!

有需要可以下载 源码

上一篇下一篇

猜你喜欢

热点阅读