手把手教学 Android用jsoup解析html

作者: 四会歌神陈子豪 | 来源:发表于2016-08-31 16:46 被阅读18624次
    1.jsoup介绍

    很多时候,我们需要从各种网页上面抓取数据,而jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

    jsoup官方文档
    https://jsoup.org/cookbook/
    中文文档
    http://www.open-open.com/jsoup/

    2.使用场景

    下面是一张关于美食的截图,可以留意到这是一个html网页,当我们想要抓取里面的数据的时候,jsoup就能帮到我们很多。

    Paste_Image.png

    接下来开始手把手教学
    • 首先,也是很重要的一步,就是下载jar包,丢到libs里面

    jar包下载地址
    http://jsoup.org/download

    • Android studio玩家可以不下载jar包,在Gradle里面加入
    dependencies {
          compile 'org.jsoup:jsoup:1.9.2'
    }
    
    • 然后,找到你心仪的网页去抓取数据

    这里我们我继续使用美食的网页,然后右键查看网页源码,或者按F12,接下来可以看到一大堆标签:

    Paste_Image.png

    找到需要的,例如上图这个 “美食天下” ,可以看到 “美食天下” 是放在以 <div class="top-bar" id="J_top_bar"> 为节点的 <a title="美食天下" ** 中,要获取这个“美食天下”**,代码可以这样写:

    try {    
        //从一个URL加载一个Document对象。
        Document doc = Jsoup.connect("http://home.meishichina.com/show-top-type-recipe.html").get();
        //选择“美食天下”所在节点
        Elements elements = doc.select("div.top-bar");    
        //打印 <a>标签里面的title
        Log.i("mytag",elements.select("a").attr("title"));
    }catch(Exception e) {    
        Log.i("mytag", e.toString());
    }
    

    接下来看一下打印出来的结果:


    Paste_Image.png

    Jsoup.connect(String url)方法从一个URL加载一个Document对象。如果从该URL获取HTML时发生错误,便会抛出 IOException,应适当处理。
    一旦拥有了一个Document,你就可以使用Document中适当的方法或它父类 ElementNode中的方法来取得相关数据。

    public class Element extends Node
    public class Document extends Element
    

    很多文章都是说一大堆原理然后放出一个简单的例子,就跟我上面简单的打了一个log一样,然后发现用起来的时候是没那么简单的。为了大家能不看文档也可以直接使用(并且看不懂那一大堆标签也可以用),我决定再举一个例子(其实也就是比上面多打几个log):
    下图红色框框是我们要获取的数据,可以看到他们对应的节点就是蓝色圆圈里面的<div class="xxx">

    Paste_Image.png
    废话不多说上代码
    try {    
        //还是一样先从一个URL加载一个Document对象。
        Document doc = Jsoup.connect("http://home.meishichina.com/show-top-type-recipe.html").get();
    
        //“椒麻鸡”和它对应的图片都在<div class="pic">中
        Elements titleAndPic = doc.select("div.pic");
        //使用Element.select(String selector)查找元素,使用Node.attr(String key)方法取得一个属性的值
        Log.i("mytag", "title:" + titleAndPic.get(1).select("a").attr("title") + "pic:" + titleAndPic.get(1).select("a").select("img").attr("data-src"));
    
        //所需链接在<div class="detail">中的<a>标签里面
        Elements url = doc.select("div.detail").select("a");
        Log.i("mytag", "url:" + url.get(i).attr("href"));
    
        //原料在<p class="subcontent">中
        Elements burden = doc.select("p.subcontent");
        //对于一个元素中的文本,可以使用Element.text()方法
        Log.i("mytag", "burden:" + burden.get(1).text());
    
    }catch(Exception e) {    
        Log.i("mytag", e.toString());
    }
    

    大功告成,接下来看看log

    Paste_Image.png

    没有问题!那么教学可以结束了!

    注意:

    Jsoup.connect(String url)方法不能运行在主线程,否则会报NetworkOnMainThreadException


    最后上一张应用在项目的效果图:

    Paste_Image.png

    有没有发现熟悉的椒麻鸡?很酷炫有木有!


    小结

    整堂课分几步:
    1.下载jar包并丢到libs(或者在gradle)
    2.找到心仪的网页
    3.用Jsoup.connect()获取网页的document
    4.查看网页源码,对准你想要的地方,给他来一个Element.select(String selector)
    5.用Node.attr(String key)或者Element.text()方法把数据抽出来
    6.没有6了就是这么简单!

    更多精彩文章请扫描下方二维码关注微信公众号"AndroidCzh":这里将长期为您分享原创文章、Android开发经验等!
    QQ交流群: 705929135

    相关文章

      网友评论

      • Development小白zz:请问一下如果我要获取head下面meta里面的数据呢?
        Development小白zz:假如果我要提取head里面的keyword的内容
      • 蓝库知识:您好,请教一下,我得到的document文件和html中的不一样,是为什么啊?
      • 小恐龙v6:又涨姿势了 感谢博主
      • 行之丶:我的总IndexOutOfBoundsException 什么原因呢? 大佬看到了给回复一下
      • LEE_6d58:666,写的很仔细,通俗易懂
      • IT_Jason:jsoup有混淆规则吗?github上没找到相关混淆规则
      • 201e7f3210f4:推荐个以类Gson的方式解析html的框架Fruit(基于Jsoup)
        https://github.com/ghuiii/Fruit
      • leilifengxingmw:文章写的太好了,超市!
      • 蔚蓝色眼泪:抓到图片之后怎么显示出来呢,不懂,求解
      • 516ba8a9f565:我的项目Jsoup部分代码:
        new Thread(new Runnable() {
        @Override
        public void run() {
        Document doc = null;
        try{
        doc = Jsoup.connect("https://lizhenxin111.github.io/categories/Java/&quot;).get();
        }catch (Exception e){
        e.printStackTrace();
        }
        Element content = doc.getElementById("js-content"); //获得根内容
        Elements articles = content.getElementsByClass("archive-article archive-type-post"); //获取class为archive-article archive-type-post的全部数据
        for (Element article : articles){ //枚举,存储每个信息
        String title = article.text(); //标题
        String u = article.attr("href"); //href
        String url = "lizhenxin111.github.io" + u; //组合成url
        WebSet webSet = new WebSet(title, url);
        webSetList.add(webSet); //初始化数据
        }
        adapter.notifyDataSetChanged();
        }
        }).start();
      • 516ba8a9f565:请问为什么写的用Jsoup抓取数据的项目有错误,应用闪退没有任何error信息,只有verbose信息:
        02-25 16:23:22.934 24111-24111/? I/art: Late-enabling -Xcheck:jni
        02-25 16:23:23.027 24111-24111/com.example.lizhenxin.jsoup W/System: ClassLoader referenced unknown path: /data/app/com.example.lizhenxin.jsoup-2/lib/arm64
        02-25 16:23:23.077 24111-24111/com.example.lizhenxin.jsoup W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
        02-25 16:23:23.222 24111-24155/com.example.lizhenxin.jsoup I/System: core_booster, getBoosterConfig = false
        02-25 16:23:23.364 24111-24159/com.example.lizhenxin.jsoup I/OpenGLRenderer: Initialized EGL, version 1.4
        02-25 16:23:23.444 24111-24155/com.example.lizhenxin.jsoup I/System: core_booster, getBoosterConfig = false
        02-25 16:23:23.720 24111-24111/com.example.lizhenxin.jsoup I/Process: Sending signal. PID: 24111 SIG: 9

        代码下面贴
      • 4cd555705ece:感谢楼主,找了好多才发现这篇满意的
      • dce9da8018d8:不错不错,准备参考
      • 2171f8c962c4:之前写的一个PokemonGo服务器状态检测的小DEMO,也是用jsoup抓的信息,有兴趣的可以简单参考下...没太大技术含量...
        https://github.com/onewilk/PGStatus
      • 莫离境:666受用了。抓个动漫网试试
        四会歌神陈子豪: @Naive_Boy ☺
      • cfanr:假如网页分页的话,怎么弄?如何模拟请求?
        四会歌神陈子豪: @cfanr 😳在加载更多的监听里改url,暂时没想到别的方法
        cfanr:@四会歌神陈子豪 我说的是自动触发的,地址没变的,也就是说滑到底自动加载更多的情况(url未变化)
        四会歌神陈子豪:@cfanr 分页的话,要改地址,例如http://home.meishichina.com/show-top-type-recipe-page.html第一页,http://home.meishichina.com/show-top-type-recipe-page-2.html就是第二页,这样
      • 3ec5a9fb0d5a:有源码下载吗?
        3ec5a9fb0d5a:@四会歌神陈子豪好的好的
        四会歌神陈子豪: @请叫我伟哥哥 没有哦,jsoup使用简便我就没放demo上来。不懂的地方可以看看官方的api
      • Wang_Yi:这个可以做爬虫吗
        四会歌神陈子豪:@donnnn 可以
      • Wower_Lau:哇,受益匪浅 :pray:
      • Weavey:66666

      本文标题:手把手教学 Android用jsoup解析html

      本文链接:https://www.haomeiwen.com/subject/cgufettx.html