整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Jsoup解析Html标签(Java后台解析)

时候编辑器传到后台的内容是带Html标签的,或者有时候需要形成一个完整的Html文档,也或者需要解析其中的文字(text()),Java后台处理用Jsoup非常方便,也可以用选择器快速获取元素,类似于jQuery。获取到文档对此之后对其处理与JS处理DOM一样方便,选取元素也类似于JS,也有类似于jQuery的语法,官方的解释

1.最基本的解析Html字符串

 @Test
 public void testHtmlToString2() {
 String html = "<p>这是一个段落<img src=\"test.img\"/>内容;</p>";
 Document doc = Jsoup.parse(html);
 System.out.println(doc); // 输出带标签的html文档
 System.out.println("---------------------\n"+doc.text()); // 输出内容
 Elements element = doc.getElementsByTag("p");
 System.out.println("---------------------\n"+element.get(0).html());
 }

结果:

<html>
 <head></head>
 <body>
 <p>这是一个段落<img src="test.img">内容;</p>
 </body>
</html>
---------------------
这是一个段落内容;
---------------------
这是一个段落<img src="test.img">内容;

2.解析字符串

 // 解析html字符串
 @Test
 public void testHtmlToString() {
 String html = "<html><head><title>First parse</title></head>"
 + "<body><p style='center'>Parsed HTML into a doc.</p></body></html>";
 Document doc = Jsoup.parse(html);
 System.out.println(doc); // 输出带标签的html文档
 System.out.println("---------------------\n"+doc.text()); // 输出内容
 }

结果:

<html>

<head>

<title>First parse</title>

</head>

<body>

<p style="center">Parsed HTML into a doc.</p>

</body>

</html>

---------------------

First parse Parsed HTML into a doc.

3.// 解析body片段

 @Test
 public void test2() {
 String html = "<div><p>Lorem ipsum.</p>";
 Document doc = Jsoup.parseBodyFragment(html);
 System.out.println(doc);
 System.out.println(doc.text());
 }

结果:

<html>

<head></head>

<body>

<div>

<p>Lorem ipsum.</p>

</div>

</body>

</html>

Lorem ipsum.

4.// 解析一个url与用选择器选择元素(相当于查看源码)

 @Test
 public void test4() throws IOException {
 Document doc = Jsoup.connect("http://qiaoliqiang.cn:8080/").get();
 String title = doc.title();// 获取title
 System.out.println(title);
 System.out.println("---------------------\n"+doc.toString()+"---------------------\n");// 输出文档全部
 Elements links = doc.getElementsByTag("a");
 for (Element ele : links) {
 System.out.println(ele.toString());
 }
 }

Apache Tomcat/7.0.72

---------------------

<!doctype html>

<html lang="en">

<head>

<title>Apache Tomcat/7.0.72</title>

<link href="favicon.ico" rel="icon" type="image/x-icon">

<link href="favicon.ico" rel="shortcut icon" type="image/x-icon">

..........

5.选择器解析HTML并且提取input的value值:(获取元素的属性)

 /**
 * <span class="bigNum">二</span>、
 * <span><input class="el_modifiedTitle" value="多选题" type="text"> </span>
 * <span>(每到题 <input class="el_modifiedGrade" value="2" type="text"> </span>
 * <span> 分;共</span><span class="numTotal">4分/</span>
 * <span class="numQues">2题)</span>
 * 
 * @param html
 * @return
 */
 // 去掉大题的标签
 public static String removeBigQues(String html) {
 StringBuffer sb = new StringBuffer();
 Document doc = Jsoup.parse(html);
 System.out.println(doc);
 System.out.println(doc.text());
 sb.append(doc.select(".bigNum").get(0).text() + ". ");
 sb.append(doc.select(".el_modifiedTitle").get(0).attr("value"));
 sb.append(doc.select("span").get(2).text() + doc.select(".el_modifiedGrade").get(0).attr("value"));
 sb.append(doc.select("span").get(3).text());
 sb.append(doc.select("span").get(4).text());
 sb.append(doc.select("span").get(5).text());
 System.out.println(sb.toString());
 return sb.toString();
 }

补充:今天发现Jsoup竟然没有解析元素style的方法,所以只能自己手写

先获取到style属性,再对style属性进行处理,例如:

 String style = "position: absolute; width: 500px; height: 552px;";
 String extract = "width";
 if (style.contains(extract)) {
 style = style.substring(style.indexOf(extract));
 System.out.println(style);
 style = style.substring(0, style.indexOf(";"));
 System.out.println(style);
 String attr = style.substring(style.indexOf(":") + 2);
 System.out.println(attr.substring(0, attr.indexOf("px")));
 }

补充:元素的html()与outerHtml()的区别

html()会返回包括子元素的内容以及标签,不包括自己

outerHtml()会返回包括自己在内的元素。

在jQuery中如果返回子元素的内容也是html(),如果返回包括自己的内容需要用$("#chartdiv").prop("outerHTML");//会返回包括自己在内的内容

soup简介

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





官网地址:
http://jsoup.org/


在官网中下载 jsou-1.8.3.jar 文件,添加到自己项目的lib库中,便可使用Jsoup提供的api,官网中也提供了一套使用指南(Cookbook),便于开发者借鉴。
Jsoup解析HTML得到一个Document对象,通过操作Document的属性来获取HTML页面内容,所以,在开始之前,先介绍一下XML中Node、Element、Document等这些相关概念的区别,防止因概念混淆而导致乱用错用。

相关概念

  • Jsoup中的继承关系

    public abstract class Node implements Cloneable
    public class Element extends Node
    public class Document extends Element

    从Jsoup源码对三者的定义可以看出如下一个树形继承关系:

  1. Node(节点)
    从上述继承关系上可以明确一点,文档中的所有内容都可以看做是一个节点。节点有很多种类型:属性节点(Attribute)、注释节点(Note)、文本节点(Text)、元素节点(Element)等,通常所说的节点是这些多种节点的统称。

  2. Element(元素)
    相比节点而言,元素则是一个更小范围的定义。元素继承于节点,是节点的子集,所以一个元素也是一个节点,节点拥有的公有属性和方法在元素中也能使用。

  3. Document(文档)
    文档继承于元素,指整个HTML文档的源码内容,通过 System.out.println(document.toString()); 即可在控制台打印出网页源码内容。

  4. 相互转换
    基于Node、Element和Document之间的“缠绵”关系,可以利用各个类中提供的方法适当转换获取所需对象,以供使用。

    使用案例

    Jsoup解析Html获取Document对象的方式分为三类:在线Url、Html文本字符串、文件,对应API如下

  • connect(String url)

  • parse(String html)

  • parse(File in, String charsetName)


    在获取到Document对象之后,可以结合HTML源码,利用Jsoup提供的api通过class、tag、id、attribute等相关属性获取对应Element,进而得到所需要的网页内容。
    下面以Jsoup的官网Cookbook页面为例,解析并获取页面目录内容。
    网页内容:





    网页源码:

    <!DOCTYPE html>
    <!-- saved from url=(0031)http://www.open-open.com/jsoup/ -->
    <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>jsoup开发指南,jsoup中文使用手册,jsoup中文文档</title>
    <meta name="keywords" content="jsoup开发指南,jsoup中文使用手册,jsoup中文文档,jsoup java html解析器">
    <meta name="description" content="jsoup Cookbook中文版 - 由http://www.open-open.com翻译整理"><link rel="stylesheet" type="text/css" href="./jsoup开发指南,jsoup中文使用手册,jsoup中文文档_files/style.css">
    </head><body class="n1-cookbook">
    <div class="wrap">
    <div class="header">
    <div class="nav-sections">
    <ul>
    <li class="n1-home">
    <h4><a href="http://jsoup.org/">jsoup</a></h4></li>
    <li class="n1-news"><a href="http://jsoup.org/news/">新闻</a></li>
    <li class="n1-bugs"><a href="http://jsoup.org/bugs">bugs</a></li>
    <li class="n1-discussion"><a href="http://jsoup.org/discussion">讨论</a></li>
    <li class="n1-download"><a href="http://jsoup.org/download">下载</a></li>
    <li class="n1-api"><a href="http://jsoup.org/apidocs/">api参考</a></li>
    <li class="n1-cookbook"><a href="http://jsoup.org/cookbook/">Cookbook</a></li></ul>
    </div></div>
    <div class="breadcrumb"><a href="http://jsoup.org/">jsoup</a> <span class="seperator">»</span> cookbook </div>
    <div class="content">
    <div class="col1">
    <h1>jsoup Cookbook(中文版)</h1>
    <div class="toc">
    <h3>入门</h3>
    <ol start="1">
    <li><a href="http://www.open-open.com/jsoup/parsing-a-document.htm">解析和遍历一个html文档</a></li>
    </ol>
    <h3>输入</h3>
    <ol start="2">
    <li><a href="http://www.open-open.com/jsoup/parse-document-from-string.htm">解析一个html字符串</a></li>
    <li><a href="http://www.open-open.com/jsoup/parse-body-fragment.htm">解析一个body片断</a></li>
    <li><a href="http://www.open-open.com/jsoup/load-document-from-url.htm">根据一个url加载Document对象</a></li>
    <li><a href="http://www.open-open.com/jsoup/load-document-from-file.htm">根据一个文件加载Document对象</a></li>
    </ol>
    <h3>数据抽取</h3>
    <ol start="6">
    <li><a href="http://www.open-open.com/jsoup/dom-navigation.htm">使用dom方法来遍历一个Document对象</a></li>
    <li><a href="http://www.open-open.com/jsoup/selector-syntax.htm">使用选择器语法来查找元素</a></li>
    <li><a href="http://www.open-open.com/jsoup/attributes-text-html.htm">从元素集合抽取属性、文本和html内容</a></li>
    <li><a href="http://www.open-open.com/jsoup/working-with-urls.htm">URL处理</a></li>
    <li><a href="http://www.open-open.com/jsoup/example-list-links.htm">程序示例:获取所有链接</a></li>
    </ol>
    <h3>数据修改</h3>
    <ol start="11">
    <li><a href="http://www.open-open.com/jsoup/set-attributes.htm">设置属性值</a></li>
    <li><a href="http://www.open-open.com/jsoup/set-html.htm">设置元素的html内容</a></li>
    <li><a href="http://www.open-open.com/jsoup/set-text.htm">设置元素的文本内容</a></li>
    </ol>
    <h3> html清理</h3>
    <ol start="14">
    <li><a href="http://www.open-open.com/jsoup/whitelist-sanitizer.htm">消除不受信任的html (来防止xss攻击)</a></li>
    </ol><script src="./jsoup开发指南,jsoup中文使用手册,jsoup中文文档_files/ca-pub-7963911354665843.js"></script><script type="text/javascript"><!--
    google_ad_client = "pub-7963911354665843";
    /* 728x90, 创建于 11-1-27 */
    google_ad_slot = "5890482646";
    google_ad_width = 728;
    google_ad_height = 90;
    //-->
    </script>
    <script type="text/javascript" src="./jsoup开发指南,jsoup中文使用手册,jsoup中文文档_files/show_ads.js">
    </script><ins id="aswift_0_expand" style="display:inline-table;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:728px;background-color:transparent"><ins id="aswift_0_anchor" style="display:block;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:728px;background-color:transparent"><iframe width="728" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&&s.handlers,h=H&&H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&&d&&(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_0" name="aswift_0" style="left:0;position:absolute;top:0;"></iframe></ins></ins></div></div>
    <div class="col2"></div></div>
    <div class="footer"><b>jsoup</b> html parser: copyright © 2009 - 2011 <a href="http://www.open-open.com/" rel="me"><b>jonathan hedley</b></a> </div></div>
    </body></html>
    Jsoup解析:
    import java.io.IOException;
    import java.text.ParseException;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.select.Elements;
    /**
    * @author 亦枫
    * @created_time 2016年1月5日
    * @file_user_todo Java测试类
    * @blog http://www.jianshu.com/users/1c40186e3248/latest_articles
    */
    public class JavaTest {
    /**
    * 入口函数
    * @param args
    * @throws ParseException
    */
    public static void main(String[] args) throws ParseException {
    try {
    //解析Url获取Document对象
    Document document = Jsoup.connect("http://www.open-open.com/jsoup/").get();
    //获取网页源码文本内容
    System.out.println(document.toString());
    //获取指定class的内容指定tag的元素
    Elements liElements = document.getElementsByClass("content").get(0).getElementsByTag("li");
    for (int i = 0; i < liElements.size(); i++) {
    System.out.println(i + ". " + liElements.get(i).text());
    }
    } catch (IOException e) {
    System.out.println("解析出错!");
    e.printStackTrace();
    }
    }
    }
    解析结果:

soup是一款Java的HTML解析器,主要用来对HTML解析。

在爬虫的时候,当我们用HttpClient之类的框架,获取到网页源码之后,需要从网页源码中取出我们想要的内容,

就可以使用jsoup这类HTML解析器了。可以非常轻松的实现。

虽然jsoup也支持从某个地址直接去爬取网页源码,但是只支持HTTP,HTTPS协议,支持不够丰富。

所以,主要还是用来对HTML进行解析。

其中,要被解析的HTML可以是一个HTML的字符串,可以是一个URL,可以是一个文件。

org.jsoup.Jsoup把输入的HTML转换成一个org.jsoup.nodes.Document对象,然后从Document对象中取出想要的元素。

org.jsoup.nodes.Document继承了org.jsoup.nodes.Element,Element又继承了org.jsoup.nodes.Node类。里面提供了丰富的方法来获取HTML的元素。

从URL获取HTML来解析

Document doc = Jsoup.connect("http://www.baidu.com/").get();
String title = doc.title();

其中Jsoup.connect("xxx")方法返回一个org.jsoup.Connection对象。
在Connection对象中,我们可以执行get或者post来执行请求。但是在执行请求之前,
我们可以使用Connection对象来设置一些请求信息。比如:头信息,cookie,请求等待时间,代理等等来模拟浏览器的行为。

Document doc = Jsoup.connect("http://example.com")
  .data("query", "Java")
  .userAgent("Mozilla")
  .cookie("auth", "token")
  .timeout(3000)
  .post();

获得Document对象后,接下来就是解析Document对象,并从中获取我们想要的元素了。

Document中提供了丰富的方法来获取指定元素。

使用DOM的方式来取得

getElementById(String id):通过id来获取
  getElementsByTag(String tagName):通过标签名字来获取
  getElementsByClass(String className):通过类名来获取
  getElementsByAttribute(String key):通过属性名字来获取
  getElementsByAttributeValue(String key, String value):通过指定的属性名字,属性值来获取
  getAllElements():获取所有元素

通过类似于css或jQuery的选择器来查找元素

使用的是Element类的下记方法:

public Elements select(String cssQuery)

通过传入一个类似于CSS或jQuery的选择器字符串,来查找指定元素。

例子:

File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Elements links = doc.select("a[href]"); //带有href属性的a元素
Elements pngs = doc.select("img[src$=.png]");
  //扩展名为.png的图片

Element masthead = doc.select("div.masthead").first();
  //class等于masthead的div标签

Elements resultLinks = doc.select("h3.r > a"); //在h3元素之后的a元素

选择器的更多语法(可以在org.jsoup.select.Selector中查看到更多关于选择器的语法):

tagname: 通过标签查找元素,比如:a
  ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 <fb:name> 元素
  #id: 通过ID查找元素,比如:#logo
  .class: 通过class名称查找元素,比如:.masthead
  [attribute]: 利用属性查找元素,比如:[href]
  [^attr]: 利用属性名前缀来查找元素,比如:可以用[^data-] 来查找带有HTML5 Dataset属性的元素
  [attr=value]: 利用属性值来查找元素,比如:[width=500]
  [attr^=value], [attr$=value], [attr=value]: 利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href=/path/]
  [attr~=regex]: 利用属性值匹配正则表达式来查找元素,比如: img[src~=(?i).(png|jpe?g)]
  *: 这个符号将匹配所有元素

Selector选择器组合使用
  el#id: 元素+ID,比如: div#logo
  el.class: 元素+class,比如: div.masthead
  el[attr]: 元素+class,比如: a[href]
  任意组合,比如:a[href].highlight
  ancestor child: 查找某个元素下子元素,比如:可以用.body p 查找在"body"元素下的所有 p元素
  parent > child: 查找某个父元素下的直接子元素,比如:可以用div.content > p 查找 p 元素,也可以用body > * 查找body标签下所有直接子元素
  siblingA + siblingB: 查找在A元素之前第一个同级元素B,比如:div.head + div
  siblingA ~ siblingX: 查找A元素之前的同级X元素,比如:h1 ~ p
  el, el, el:多个选择器组合,查找匹配任一选择器的唯一元素,例如:div.masthead, div.logo

伪选择器selectors
  :lt(n): 查找哪些元素的同级索引值(它的位置在DOM树中是相对于它的父节点)小于n,比如:td:lt(3) 表示小于三列的元素
  :gt(n):查找哪些元素的同级索引值大于n,比如: div p:gt(2)表示哪些div中有包含2个以上的p元素
  :eq(n): 查找哪些元素的同级索引值与n相等,比如:form input:eq(1)表示包含一个input标签的Form元素
  :has(seletor): 查找匹配选择器包含元素的元素,比如:div:has(p)表示哪些div包含了p元素
  :not(selector): 查找与选择器不匹配的元素,比如: div:not(.logo) 表示不包含 class="logo" 元素的所有 div 列表
  :contains(text): 查找包含给定文本的元素,搜索不区分大不写,比如: p:contains(jsoup)
  :containsOwn(text): 查找直接包含给定文本的元素
  :matches(regex): 查找哪些元素的文本匹配指定的正则表达式,比如:div:matches((?i)login)
  :matchesOwn(regex): 查找自身包含文本匹配指定正则表达式的元素
注意  :上述伪选择器索引是从0开始的,也就是说第一个元素索引值为0,第二个元素index为1等

通过上面的选择器,我们可以取得一个Elements对象,它继承了ArrayList对象,里面放的全是Element对象。

接下来我们要做的就是从Element对象中,取出我们真正需要的内容。

通常有下面几种方法:

Element.text()

这个方法用来取得一个元素中的文本。

Element.html()或Node.outerHtml()

这个方法用来取得一个元素中的html内容

Node.attr(String key)

获得一个属性的值,例如取得超链接<a href="">中href的值

文本福利:

为了让大家更快速高效的学习,我整理了一份 Java 全能资料包含(高可用、高并发、高性能及分布式、 Jvm 性能调优、 Spring 源码, MyBatis , Netty , Redis , Kafka , Mysql , Zookeeper , Tomcat , Docker , Dubbo , Nginx ,架构,面试等等…)

大家可自行领取!

领取方式-关注 私信回复我 6