一、Jsoup概述
1.1、简介
jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,
可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
1.2、主要功能
1、从一个URL,文件或字符串中解析HTML
2、使用DOM或CSS选择器来查找、取出数据
3、可操作HTML元素、属性、文本
注意:jsoup是基于MIT协议发布的,可放心使用于商业项目。
1.3、maven地址
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
二、jsoup实际操作
-
从String解析文档
String html = "<html><head><title>First parse</title></head>" + "<body><p>Parsed HTML into a doc.</p></body></html>"; Document doc = Jsoup.parse(html);
-
解析一个标签
String html = "<div><p>Lorem ipsum.</p>"; Document doc = Jsoup.parseBodyFragment(html); Element body = doc.body();
-
加载url中的文档
//请求jsoup主页并获取到网页的标题 Document doc = Jsoup.connect("https://jsoup.org").get(); String title = doc.title(); System.out.println("获取jsoup页面的标题:" + title);
-
从文件中加载文档
File input = new File("/tmp/input.html"); Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
-
用Dom方法提取数据
Document doc = Jsoup.connect("https://jsoup.org") Element content = doc.getElementById("content"); Elements links = content.getElementsByTag("a"); for (Element link : links) { String linkHref = link.attr("href"); String linkText = link.text(); } <--------------获取标签的方法------------------> - `getElementById(String id)` //根据ID 查询 - `getElementsByTag(String tag)` //根据标签名 - `getElementsByClass(String className)` //根据class 名 - `getElementsByAttribute(String key)` (及相关方法) - 元素的兄弟姐妹:`siblingElements()`,`firstElementSibling()`,`lastElementSibling()`,`nextElementSibling()`,`previousElementSibling()` - 图:`parent()`,`children()`,`child(int index)` <--------------获取元素属性的方法----------------> - `attr(String key)`获取和`attr(String key, String value)`设置属性 - `attributes()` 获得所有属性 - `id()`,`className()`和`classNames()` - `text()`获取和`text(String value)`设置文本内容 - `html()`获取和`html(String value)`设置内部HTML内容 - `outerHtml()` 获取外部HTML值 - `data()`获取数据内容(例如`script`和`style`标签) - `tag()` 和 `tagName()` <---------------处理HTML的方法------------------> - `append(String html)`, `prepend(String html)` - `appendText(String text)`, `prependText(String text)` - `appendElement(String tagName)`, `prependElement(String tagName)` - `html(String value)`
-
使用select选择器或者Jqury选择器来查找元素
Document doc = Jsoup.connect("https://jsoup.org").get(); // 查询所有的a 标签 Elements links = doc.select("a[href]"); // 查询以.png结尾的src标签 Elements pngs = doc.select("img[src$=.png]"); // 查询以 div 与 class=masthead 的标签 Element masthead = doc.select("div.masthead").first(); // direct a after h3 Elements resultLinks = doc.select("h3.r > a"); jsoup元素支持[CSS]之类的选择器语法来查找匹配元素,从而允许非常强大和健壮的查询。 该`select`方法在一个可用`Document`,`Element`或在`Elements`。它是上下文的,因此您可以通过从特定元素中进行选择或通过链接选择调用来进行过滤。 Select返回一个Elements列表(as `Elements`),它提供了一系列提取和操作结果的方法。 选择器概述 - `tagname`:按标签查找元素,例如 `a` - `ns|tag`:在命名空间中按标记`fb|name`查找`<fb:name>`元素,例如查找元素 - `#id`:按ID查找元素,例如 `#logo` - `.class`:按类名查找元素,例如 `.masthead` - `[attribute]`:具有属性的元素,例如 `[href]` - `[^attr]`:具有属性名称前缀的`[^data-]`元素,例如查找具有HTML5数据集属性的元素 - `[attr=value]`:具有属性值的元素,例如`[width=500]`(也是可引用的`[data-name='launch sequence']`) - `[attr^=value]`,`[attr$=value]`,`[attr*=value]`:用与启动属性,以结束,或包含所述的值,例如元素`[href*=/path/]` - `[attr~=regex]`:具有与正则表达式匹配的属性值的元素; 例如`img[src~=(?i)\.(png|jpe?g)]` - `*`:所有元素,例如 `*` 选择器组合 - `el#id`:具有ID的元素,例如 `div#logo` - `el.class`:带有类的元素,例如 `div.masthead` - `el[attr]`:具有属性的元素,例如 `a[href]` - 任何组合,例如 `a[href].highlight` - `ancestor child`:从祖先下降的子元素,例如在类“body”的块下的任何位置`.body p`查找`p`元素 - `parent > child`:直接从父级下降的子元素,例如`div.content > p`查找`p`元素; 并`body > *`找到body标签的直接子节点 - `siblingA + siblingB`:找到兄弟B元素之后紧接着兄弟A,例如 `div.head + div` - `siblingA ~ siblingX`:找到兄弟A前面的兄弟X元素,例如 `h1 ~ p` - `el, el, el`:对多个选择器进行分组,找到与任何选择器匹配的唯一元素; 例如`div.masthead, div.logo` 伪选择器 - `:lt(n)`:找到其兄弟索引(即它在DOM树中相对于其父节点的位置)小于的元素`n`; 例如`td:lt(3)` - `:gt(n)`:查找兄弟索引大于的元素`n`; 例如`div p:gt(2)` - `:eq(n)`:查找兄弟索引等于的元素`n`; 例如`form input:eq(1)` - `:has(selector)`:查找包含与选择器匹配的元素的元素; 例如`div:has(p)` - `:not(selector)`:查找与选择器不匹配的元素; 例如`div:not(.logo)` - `:contains(text)`:查找包含给定文本的元素。搜索不区分大小写; 例如`p:contains(jsoup)` - `:containsOwn(text)`:查找直接包含给定文本的元素 - `:matches(regex)`:查找文本与指定正则表达式匹配的元素; 例如`div:matches((?i)login)` - `:matchesOwn(regex)`:查找自己的文本与指定正则表达式匹配的元素 - 注意,上面的索引伪选择器是基于0的,即第一个元素是索引0,第二个元素是1,等等 有关`Selector`完整支持的列表和详细信息,请参阅API参考。
-
从元素中提取属性,文本和Html
- 要获取属性的值,请使用该`Node.attr(String key)`方法 - 对于元素(及其组合子元素)上的文本,请使用 `Element.text()` - 对于HTML,使用`Element.html()`或`Node.outerHtml()`适当 上述方法是元素数据访问方法的核心。还有其他人: - `Element.id()` - `Element.tagName()` - `Element.className()` 和 `Element.hasClass(String className)` 所有这些访问器方法都有相应的setter方法来更改数据。
-
使用url
Document doc = Jsoup.connect("http://jsoup.org").get(); Element link = doc.select("a").first(); String relHref = link.attr("href"); // == "/" String absHref = link.attr("abs:href"); // "http://jsoup.org/" 在HTML元素中,URL通常是相对于文档的位置编写的:`<a href="/download">...</a>`。当您使用该`Node.attr(String key)`方法获取href属性时,它将按照源HTML中的指定返回。 如果要获取绝对URL,则会有一个属性键前缀`abs:`,该前缀将导致根据文档的基URI(原始位置)解析属性值:`attr("abs:href")` 对于此用例,在解析文档时指定基URI非常重要。 如果您不想使用`abs:`前缀,还有一个方法`Node.absUrl(String key)`可以执行相同的操作,但可以通过自然属性键进行访问。
-
修改属性
问题
您有一个已解析的文档,您希望在将其保存到磁盘之前更新属性值,或者将其作为HTTP响应发送。
解析
使用属性setter方法
Element.attr(String key, String value)
,和Elements.attr(String key, String value)
。如果需要修改
class
元素的属性,请使用Element.addClass(String className)
和Element.removeClass(String className)
方法。该
Elements
集合具有批量归属和类方法。例如,要为div中的rel="nofollow"
每个a
元素添加一个属性:doc.select("div.comments a").attr("rel", "nofollow");
-
修改元素的html
Element div = doc.select("div").first(); // <div></div> div.html("<p>lorem ipsum</p>"); // <div><p>lorem ipsum</p></div> div.prepend("<p>First</p>"); div.append("<p>Last</p>"); // now: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div> Element span = doc.select("span").first(); // <span>One</span> span.wrap("<li><a href='http://example.com/'></a></li>"); // now: <li><a href="http://example.com"><span>One</span></a></li> 您还可以使用`Element.prependElement(String tag)`和`Element.appendElement(String tag)`方法创建新元素,并将它们作为子元素插入到文档流中。
-
设置标签的文本内容
// 先查到需要更改的div <div></div> Element div = doc.select("div").first(); // <div>five > four</div> //清除元素中的任何现有内部HTML,并将其替换为提供的文本。 div.text("five > four"); //添加文本节点到元素的内部HTML的开始 div.prepend("First "); //添加文本节点到元素的内部HTML的结束时 div.append(" Last"); // now: <div>First five > four Last</div>
-
清理不受信任的Html
String unsafe = "<p><a href='http://example.com/' οnclick='stealCookies()'>Link</a></p>"; String safe = Jsoup.clean(unsafe, Whitelist.basic()); // now: <p><a href="http://example.com/" rel="nofollow">Link</a></p>
注:以上内容由多处转载,如有议论请联系我删除
三、实战操作
-
获取京东搜索后的各类信息
----主方法 public class getDd { public static void main(String[] args) throws IOException { new DdUtils().getDd("心理学").forEach(System.out::println); } } ---实体类 @Data @NoArgsConstructor @AllArgsConstructor public class Dd { private String title; private String price; private String detail; private String img; } ---工具类 public class JdUtils { public static List<Jd> getJD(String name) throws IOException { //获取请求 String url="https://search.jd.com/Search?keyword="+name; //解析网页 获得的Document对象可以适用所有js Document document = Jsoup.parse(new URL(url), 30000); //使用js 通过id获取该标签内的所有标签 Element element = document.getElementById("J_goodsList"); /* 打印该元素的网页代码 System.out.println(element.html()); */ //通过所有指定的标签元素 ArrayList<Jd> list = new ArrayList<Jd>(); Elements elements = element.getElementsByTag("li"); //遍历所有的li元素,获取想要的元素 for(Element el:elements){ String title=el.getElementsByClass("p-name").eq(0).text(); String price=el.getElementsByClass("p-price").eq(0).text(); String img=el.getElementsByTag("img").eq(0).attr("data-lazy-img"); //将获得的数据封装成一个对象 Jd jd = new Jd(title, price, "https"+img); list.add(jd); } return list; } }
-
获取当当网搜索后的各类信息
---主方法 public class getDd { public static void main(String[] args) throws IOException { new DdUtils().getDd("心理学").forEach(System.out::println); } } ---实体类 @Data @NoArgsConstructor @AllArgsConstructor public class Dd { private String title; private String price; private String detail; private String img; } ---工具类 public class DdUtils { public List<Dd> getDd(String name) throws IOException { // //获取要爬取的网站 String url = "https://search.dangdang.com/?key=" + name; // //解析该网站 Document document = Jsoup.parse(new URL(url), 30000); System.out.println(document.html()); 打印获取网页时的状态,可以查看一些懒加载的真实属性 //获取指定的标签 Element element = document.getElementById("search_nature_rg"); //获取标签内的所有指定的标签 Elements elements = element.getElementsByTag("li"); List<Dd> list = new ArrayList<>(); for (Element el : elements) { String title = el.getElementsByTag("a").eq(0).attr("title"); String price = (el.getElementsByClass("search_now_price").eq(0).html().split(";", 2))[1]; String detail = el.getElementsByClass("detail").eq(0).html(); String img = ("http:" + el.getElementsByTag("img").eq(0).attr("data-original")); Dd dd = new Dd(title, price, detail, img); list.add(dd); } return list; } }
四、参考文档
使用到的中文转码 UrlEncoder.encode(中文,“UTF-8”)