Jsoup使用总结
来源:互联网 发布:金域名都公寓价格 编辑:程序博客网 时间:2024/05/21 19:37
1. 概述
对HTML页面的解析,之前我一般使用HTMLParser,详细见HTMLParser的学习系列 - 学习总结,但是这个项目已经停止更新。现在比较好的解析HTML的控件是Jsoup。本文对Jsoup的用法做个总结 。
Jsoup的主要功能有三部分组成:
- 从字符串,网页,本地文件等方式生成Documentn
- 在生成Doucment后,根据Dom和css或类似jquery的selector语法获取Element,然后再从Elements中获取节点属性、文本、html
- 对Element的进行操作,包括HTML的值、节点内容的值和设置节点属性的值
下方每节对以上三点进行逐一演示。
POM.xml 配置
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.10.2</version></dependency>
2. 生成Document
JSOUP通过不同方式生成Document,主要有以下三种:
1. 字符串
2. 网页
3. 本地文件
2.1 从字符串生成Document
关键方法:Jsoup.parse
代码
/** * 将字符串转化为Document * * html: https://jsoup.org/cookbook/input/parse-document-from-string */ public void parseDocumentFromString() { String html = "<html><head><title>First parse</title></head>" + "<body><p>Parsed HTML into a doc.</p></body></html>"; Document doc = Jsoup.parse(html); logger.info("parseDocumentFromString content={}", doc); }
输出结果
parseDocumentFromString content=<html> <head> <title>First parse</title> </head> <body> <p>Parsed HTML into a doc.</p> </body></html>
2.2 从网页生成Document
关键方法: Jsoup.connect
代码
/** * 从网络上加载网页并转化为Document * * html: https://jsoup.org/cookbook/input/load-document-from-url */ public void loadDocumentFromURL() { Document doc; try { doc = Jsoup.connect("https://www.baidu.com/").get(); // 从document中获取title值 String title = doc.title(); logger.info("LoadDocumentFromURL title={}", title); } catch (IOException e) { e.printStackTrace(); } }
输出:由于页面太大,这里没有打印页面内容,只是输出页面的title值
LoadDocumentFromURL title=百度一下,你就知道
2.3 从本地文件生成Document
本地测试文件: loadDocumentFromFile.html
<html><body>.. body</body></html>
代码
关键方法: Jsoup.parse
/** * 从本地加载文件并转化为Document * * html: https://jsoup.org/cookbook/input/load-document-from-file */ public void loadDocumentFromFile() { URL fileUrl = LoadParseDocument.class.getResource("/com/hry/tool/jsoup/doc/loadDocumentFromFile.html"); File input = new File(fileUrl.getFile()); try { /* The baseUri parameter is used by the parser to resolve relative URLs in the document * before a <base href> element is found. If that's not a concern for you, * you can pass an empty string instead. */ Document doc = Jsoup.parse(input, "UTF-8", "https://www.baidu.com/"); logger.info("LoadDocumentFromFile content={}", doc); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出
LoadDocumentFromFile content=<html> <head></head> <body> .. body </body></html>
3. 获取Element及节点属性、文本、html
在上一节中已经生成Document,下面就可以对这个document进行操作,操作的主要单位是Element,下面介绍如何选取elment及获取elment的内容。
本地包含的主要内容获取节点信息:
1. 获取Element,获取的方式有二种: a DOM; b 通过css或类似jquery的selector语法
2. 获取节点属性、文本、html
3.1 获取Element
a DOM
代码
/** * 调用document的类似DOM的方法获取Element * * html: https://jsoup.org/cookbook/extracting-data/dom-navigation * @throws IOException */ public void extractDataByDOM() throws IOException{ Document doc = Jsoup.connect("https://www.baidu.com/").get(); Element lg = doc.getElementById("lg"); logger.info("getElementById lg = {}", lg); Elements links = doc.getElementsByTag("a"); for (Element link : links) { String linkHref = link.attr("href"); String linkText = link.text(); logger.info("linkHref={}, linkText={}",linkHref, linkText); } }
输出
输出内容过多,略
b 通过css或类似jquery的selector语法
点击查看全部的selector语法
测试文件: extractDataByCSSOrJqueryLikeSelectorSyntax.html
<html><header> <h3 class="r">h3<a href="/test/h3"></a></b></h3></header><body>.. body<div> <a href="/test" >test</a> <a href="/test2" >test2</a></div><div> <img alt="test" src="/image/a.png" /> <img alt="test2" src="/image/b.png" /></div><div> <div class="masthead">masthead</div></div></body></html>
代码
/** * 通过css或类似jquery的selector语法 * * html: https://jsoup.org/cookbook/extracting-data/selector-syntax * @throws IOException */ public void extractDataByCSSOrJqueryLikeSelectorSyntax() throws IOException{ URL fileUrl = LoadParseDocument.class.getResource("/com/hry/tool/jsoup/extractingdata/extractDataByCSSOrJqueryLikeSelectorSyntax.html"); File input = new File(fileUrl.getFile()); Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/"); // 获取所有的a节点 Elements links = doc.select("a[href]"); logger.info("links = {}", links); // 获取img的src以.png结果结尾 Elements pngs = doc.select("img[src$=.png]"); logger.info("pngs = {}", pngs); // 获取class=masthead的div节点 Element masthead = doc.select("div.masthead").first(); logger.info("masthead = {}", masthead); // 获取class=r的h3节点下面的a节点 Elements resultLinks = doc.select("h3.r > a"); // direct a after h3 logger.info("resultLinks = {}", resultLinks); }
输出: 省略部分日志内容,方便查看
links = <a href="/test/h3"></a><a href="/test">test</a><a href="/test2">test2</a>pngs = <img alt="test" src="/image/a.png"><img alt="test2" src="/image/b.png">masthead = <div class="masthead">masthead</div>
3.2 获取节点属性、文本、html
代码
/** * 获取节点属性、文本、html * * html: https://jsoup.org/cookbook/extracting-data/attributes-text-html */ public void extractAttributesTextAndHTML(){ String html = "<p>An <a href='/abc'><b>example</b></a> link.</p>"; // 指定baseUri的值,在使用abs:attr会使用到 Document doc = Jsoup.parse(html, "http://example.com/"); Element link = doc.select("a").first(); /** * text获取所有子节点的文本并组合在一一起 * 如:HTML <p>Hello <b>there</b> now! </p>, --》 调用p.text() --》输出: "Hello there now!" */ String text = doc.body().text(); // "An example link" logger.info("text={}", text); // 获取link的href属性值 String linkHref = link.attr("href"); // /abc // 在href前面加上abs,会在现有的href(如/abc)的前面别上Jsoup.parse(html, "http://example.com/")里指定的baseUri值 String absLinkHref = link.attr("abs:href"); // http://example.com/abc logger.info("linkHref={}, absLinkHref={}",linkHref, absLinkHref); // 获取link里所有字节点的内容组合在一起 String linkText = link.text(); // "example"" logger.info("linkText={}", linkText); // 获取本节点所有HTML文本信息 String linkOuterH = link.outerHtml(); // "<a href="http://example.com"><b>example</b></a>" logger.info("linkOuterH={}", linkOuterH); // 获取本节点字节点的html文本信息 String linkInnerH = link.html(); // "<b>example</b>" logger.info("linkInnerH={}", linkInnerH); }}
输出:省略部分日志,方便阅读
text=An example link.linkHref=/abc, absLinkHref=http://example.com/abclinkText=examplelinkOuterH=<a href="/abc"><b>example</b></a>linkInnerH=<b>example</b>
4. 设置节点值
设置节点值,主要有在以下方式:
1. 设置节点HTML的值
2. 设置节点内容的值
3. 设置节点属性的值
公共测试文件
<html><body>.. body<div></div><span>One</span></body></html>
从本地文件造成Document文本
private Document getDoucment() throws IOException{ URL fileUrl = LoadParseDocument.class.getResource("/com/hry/tool/jsoup/modifyingdata/modifyingData.html"); File input = new File(fileUrl.getFile()); Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/"); return doc; }
4.1 设置节点HTML的值
设置节点的html内容:
- Element.html:使用新的HTML替换旧的值
- Element.prepend:将新html添加到指定节点内部的最前面
- Element.append:将新html添加到指定节点内部的最后面
Element.wrap:将指定节点封装到html最里面
代码:
/** * 设置节点的html内容: * 1. html:使用新的HTML替换旧的值 * 2. prepend:将新html添加到指定节点内部的最前面 * 3. append:将新html添加到指定节点内部的最后面 * 4. wrap:将指定节点封装到html最里面 * * html: https://jsoup.org/cookbook/modifying-data/set-html * @throws IOException */public void setHTMLofAnElement() throws IOException{ Document doc = getDoucment(); // 获取div节点 Element div = doc.select("div").first(); // <div></div> // 使用新的HTML替换div旧的html值 div.html("<p>lorem ipsum</p>"); // <div><p>lorem ipsum</p></div> // 将新html添加到div内部的最前面 div.prepend("<p>First</p>"); // <div><p>First</p><p>lorem ipsum</p></div> // 将新html添加到div内部的最后面 div.append("<p>Last</p>"); // now: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div> logger.info("now div={}", div); Element span = doc.select("span").first(); // <span>One</span> // 将span节点封装到html最里面 --》 <li><a href="http://example.com"><span>One</span></a></li> span.wrap("<li><a href='http://example.com/'></a></li>"); logger.info("doc={}", doc);}
输出:
2017-06-07 22:35:48.271 INFO 6644 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : now div=<div> <p>First</p> <p>lorem ipsum</p> <p>Last</p></div>2017-06-07 22:35:48.271 INFO 6644 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : doc=<html> <head></head> <body> .. body <div> <p>First</p> <p>lorem ipsum</p> <p>Last</p> </div> <li><a href="http://example.com/"><span>One</span></a></li> </body></html>
4.2 设置节点内容的值
修改节点内容
1. Element.text: 完全替换内容
2. Element.prepend:在节点的内容最前面加内容
3. Element.append:在节点的内容最后面加内容
/** * 修改节点内容 * 1. 完全替换内容 * 2. 在节点的内容最前面加内容 * 3. 在节点的内容最后面加内容 * * html: https://jsoup.org/cookbook/modifying-data/set-text * @throws IOException */ public void setTextContentofAnElement() throws IOException{ Document doc = getDoucment(); Element div = doc.select("div").first(); // <div></div> // 替换div里的内容 输出 --> <div>five four</div> div.text("five four"); logger.info("text = {}", div); // 在div的内容最前面加内容 输出 --> <div> First five four</div> div.prepend("First "); logger.info("prepend = {}", div); // 在div的内容最后面加内容 输出 --> <div>First five four Last</div> div.append(" Last"); logger.info("append = {}", div); }
输出:
2017-06-07 22:39:20.289 INFO 11476 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : text = <div> five four</div>2017-06-07 22:39:20.289 INFO 11476 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : prepend = <div> First five four</div>2017-06-07 22:39:20.289 INFO 11476 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : append = <div> First five four Last</div>
4.3 设置节点属性的值
设置节点的属性和class值
- element.attr: 设置属性
- element.addClass: 设置class
代码
/** * 设置节点的属性和class值 * 1. 设置属性 * 2. 设置class * * html:https://jsoup.org/cookbook/modifying-data/set-attributes * @throws IOException */ public void setAttributeValues() throws IOException{ Document doc = getDoucment(); Element div = doc.select("div").first(); // 在div节点上增加属性和其值:输出 --> <div title="nofollow"></div> div.attr("title", "nofollow"); logger.info("div={}", div); // 在div节点上增加class和其值:输出 --> <div title="nofollow" class="round-box"></div> div.addClass("round-box"); logger.info("div={}", div); }
输出
2017-06-07 22:39:44.466 INFO 11280 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : div=<div title="nofollow"></div>2017-06-07 22:39:44.466 INFO 11280 --- [ main] c.h.t.jsoup.modifyingdata.ModifyingData : div=<div title="nofollow" class="round-box"></div>
5. 代码 ##
详细代码见 github代码
- Jsoup使用总结
- Jsoup使用总结
- 使用jsoup的几点小总结
- Jsoup总结
- Jsoup总结
- jsoup总结
- Jsoup总结
- Jsoup总结
- jsoup使用
- jsoup使用
- jsoup使用
- Jsoup使用
- JSoup 代码总结
- HtmlUnit+Jsoup学习总结
- Jsoup学习总结
- Jsoup学习总结
- Jsoup学习总结
- jsoup学习总结
- Linux之守护进程
- hadoop多节点集群搭建过程中错误:No such file or directoryhdfs,logs提示出现出现^M的解决办法
- linux系统命令总结(二)
- xamarin学习笔记A05(安卓RecycleView简单显示)
- INotify的介绍和使用
- Jsoup使用总结
- 编译内核错误:"mkimage" command not found
- pat-a1064. Complete Binary Search Tree (30)
- 通讯录小感想(1)
- 《数据结构学习与实验指导》2-5:求集合数据的均方差
- 【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类
- C语言学习
- H264 术语
- 是热爱不是质疑