欢迎使用CSDN-markdown编辑器
来源:互联网 发布:pychram软件运行环境 编辑:程序博客网 时间:2024/06/14 22:57
Jsoup
by bcli
简介
用于解析HTML5
文本的JAVA
类。对于未封闭的HTML如<p>paragraph
也可以正确处理。简单应用举例:
// 获得维基百科主页Document doc = Jsoup.connect("http://en.wikipedia.org/").get();// 获得id为mp-itn,中,<b>中的<a> (使用类CSS语法)Elements newsHeadlines = doc.select("#mp-itn b a");
在开头标有?的表示不能完全理解,存在疑惑。这篇文档完全根据jsoup官方文档翻译、整理而来
原文档请看文章结尾的参考资料->jsoup官网
,API请查看参考资料->jsoup API
安装
eclipse添加jsoup类
- 官网http://jsoup.org/download下载jar包
- 将jar包拷贝到一个易于管理的目录下
- 右键点击项目目录,选择
Build Path
->Configure Build Path
->Add External JAR
->选择jsoup JAR包 - 在java类中
import org.jsoup.*
就可以使用jsoup的所有类了
常用函数
Jsoup.parse(html)
解析DOM
// 定义DOM文本String html = "<html><head><title>First parse</title></head>" + "<body><p>Parsed HTML into a doc.</p></body></html>";// 解析DOM文本Document doc = Jsoup.parse(html);
Jsoup.parseBodyFragment(String html_body)
解析<body>
中的的DOM,比如:
// 定义一个未闭合的DOM文本(无<head>)String html = "<div><p>Lorem ipsum.</p>";// 将文本按照body中的内容解析Document doc = Jsoup.parseBodyFragment(html);// 获得解析后的DOMElement body = doc.body();
这个函数等同于
// 定义一个完整的HTML DOMString html = "<html><head><title>TITLE</title></head><body><div><p>Lorem ipsum.</p></body></html>";// 解析此HTML DOMDocument doc = Jsoup.parse(html);// 获得此DOM的body部分doc.getElementsByTag("body");
Jsoup.connect(String url)
从URL获取DOM
Document doc = Jsoup.connect("http://example.com/").get();String title = doc.title();
可设置HTTP请求参数,比如method, userAgent等:
Document doc = Jsoup.connect("http://www.baidu.com") .data("query", "Java") .userAgent("Mozilla") .cookie("auth", "token") .timeout(3000) .post();
Jsoup.parse(File in, String charsetName, String baseUri)
从文件中解析DOM
File input = new File("/tmp/input.html");// 读取文本,按照UTF-8解析Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");// 获得id为content的元素Element content = doc.getElementById("content");// 在content中,获得所有tag为<a>的元素Elements links = content.getElementsByTag("a");for (Element link : links) { // 对于每个tag为<a>的元素,获得其链接指向的URL String linkHref = link.attr("href"); // 获得其链接文本 String linkText = link.text();}
CSS元素选择函数
使用Element.select(String selector)
和Elements.select(String selector)
进行CSS选择,其中selector
使用类CSS语法。如
File input = new File("/tmp/input.html");Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");// 获得所有带有href属性的<a>Elements links = doc.select("a[href]");// 获得所有带有src属性,且src属性中含有.png的<img>Elements pngs = doc.select("img[src$=.png]");// 获得第一个,类为masthead的<div>Element masthead = doc.select("div.masthead").first();// 获得<h3>后面的<a>Elements resultLinks = doc.select("h3.r > a");
* 选择器
* 按TAG:select(“div”)
选择所有div
* ? select(div|name)
选择<div:name>
* 按ID:select("#container")
选择id="container"
* 按类:select(".col")
选择class="col"
* 按属性:select("a[href]")
选择带href
属性的<a>
* 按属性前缀:^=
* select("div[^data-]")
选择带data-....
属性的<div>
* select("div[class^=col-]")
选择类为col-....
的<div>
* 按属性后缀:$=
* select("input[$ed]")
选择带....ed
属性的<input>
* select("img[img$=.png]")
选择格式为png
的<img>
* 按属性等于:=
* select("div[width=500px]")
选择带有width
属性且width=500px
的<div>
* 按属性包含:*=
* select("a[href*=/upload/]")
选择链接中含有/upload/
的<a>
* 按属性符合正则表达式:~=
* select("img[src~=(?i)\.(png|jpe?g)]")
选择为png,jpg或jpeg
格式的<img>
* 选择所有元素:*
* 选择器组合:
* div#logo
:获得id=logo
的<div>
* div.masthead
:获得class=masthead
的<div>
* a[href]
:获得含有href
属性的<a>
* a[href].active
获得含有href
属性和class=active
的<a>
* a[href]#nav.active
获得含有href
属性,id=nav
,class=active
的<a>
* .conatiner p
获得类为container
的元素,的标签为<p>
的子元素
* .container > p
获得类为container
的元素,的标签为<p>
的第一层子元素
* .container > *
获得类为container
的元素,的所有第一层子元素
* ? div.head + div
获得A 和 B
(A和B互为同层元素且相邻)
* ? h1 ~ p
获得A ~ B
的同层元素
* div.masthead,div.logo,...
若使用逗号隔开各个条件,条件之间为或关系,选择满足任意一个条件的元素
- 伪选代码择器(注意
index
以0
开头)td:lt(3)
:选择相对于父元素<tr>
,index
小于3
的<td>
元素div p:gt(2)
:选择相对于父元素<div>
,index
大于2的<p>
元素form input:eq(1)
:选择相对于父元素<form>
,index
等于1的<input>
元素div:has(p)
获得含有<p>
的<div>
div:not(.logo)
获得类名不为logo
的<div>
p:contains(jsoup)
获得含有jsoup
的<p>
,不分大小写- ?
p:containsOwn(jsoup)
获得下一层含有jsoup
的<p>
,不分大小写 - ?
div:matches((?i)login)
获得符合正则表达式(?i)login
的<div>
- ?
div:matchesOwn((?i)login)
获得下一层符合正则表达式(?i)login
的<div>
元素操作函数
寻找元素
- 按ID查找
getElementById(String id)
- 按TAG查找
getElementsByTag(String tag)
- 按类查找
getElementsByClass(String className)
- 按属性查找
getElementsByAttribute(String key)
查找同层元素
比如下面的
<li>
是同层元素,又称sibling
兄弟元素<ul> <li> A </li> <li> B </li></ul>
获得所有同层元素
siblingElements()
- 获得第一个同层元素
firstElementSibling()
- 获得最后一个同层元素
lastElementSibling()
- 获得下一个同层元素
nextElementSibling()
- 获得上一个同层元素
previousElementSibling()
- 查找父元素或子元素:
parent(), children(), child(int index)
- 按ID查找
元素数据
- 获得属性:
attr(String key)
- 设置属性:
attr(String key, String value)
- 获得所有属性:
attributes()
- 获得id:
id()
- 获得类名:
className()
- 批量获得类名:
classNames()
- 获得文本:
text()
- 设置文本:
text(String value)
- 获得HTML:
html()
- 设置HTML:
html(String value)
- 获得外层HTML:
outerHtml()
- 获得
script
和style
之类属性中的数据:data()
- 获得
tag
:tag()
- 获得
tag
名称(如div
):tagName()
- 获得属性:
复制HTML和文本
- 前添加HTML:
prepend(String html)
- 前添加文本:
prependText(String text)
- 后添加HTML:
append(String html)
- 后添加HTML:
appendText(String text)
- 前添加元素:
prependElement(String tagName)
- 后添加元素:
appendElement(String tagName)
- 前添加HTML:
获得值、文本和HTML
- 获得属性值:
Node.attr(String key)
- 获得元素文本:
Element.text()
- 获得HTML:
Element.html()
- 获得元素id:
Element.id()
- 获得tag名:
Element.tagName()
- 获得类名:
Element.className()
是否是某个类:
Element.hasClass(String className)
// 定义HTML文本String html = "<p>An <a href='http://example.com/'><b>example</ b></a> link.</p>";// 解析DOMDocument doc = Jsoup.parse(html);// 获得第一个<a>Element link = doc.select("a").first();// 获得内容String text = doc.body().text(); // An example linkString linkHref = link.attr("href"); // http://example.com/String linkText = link.text(); // exampleString linkOuterH = link.outerHtml(); // <a href="http://example.com"><b>example</b></a>String linkInnerH = link.html(); // <b>example</b>
URL操作
有些情况下网站会使用相对URL,比如/img/profile.png
。这时,如果你已经指定了域名(使用connect命令时jsoup会自动解析域名,使用file时需要手动指定域名),你就可以使用String absHref = link.attr("abs:href");
来获得绝对路径的URL了,举例:
// 获得网站页面Document doc = Jsoup.connect("http://jsoup.org").get();// 获得第一个<a>Element link = doc.select("a").first();// 获得第一个<a>的链接String relHref = link.attr("href"); // 链接为相对链接: "/"String absHref = link.attr("abs:href"); // 使用abs:href转化为绝对链接://"http://jsoup.org/"
应用举例
程序
package org.jsoup.examples;// jsoup引用import org.jsoup.Jsoup;import org.jsoup.helper.Validate;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;import java.io.IOException;/** * Example program to list links from a URL.*/public class ListLinks { public static void main(String[] args) throws IOException { // 接受用户URL输入(只接受1个参数) Validate.isTrue(args.length == 1, "usage: supply url to fetch"); // 为URL赋值 String url = args[0]; // 打印正在获取页面 print("Fetching %s...", url); // 按照URL获取页面 Document doc = Jsoup.connect(url).get(); // 获取所有含有href属性的<a> Elements links = doc.select("a[href]"); // 获取所有含有src的多媒体元素(主要应为图片) Elements media = doc.select("[src]"); // 获得所有含有href属性的link Elements imports = doc.select("link[href]"); // 输出多媒体元素的个数 print("\nMedia: (%d)", media.size()); // 处理多媒体元素 for (Element src : media) { // 获得<img>标签 if (src.tagName().equals("img")) { // 输出<img>属性 print( " * %s: <%s> %sx%s (%s)", src.tagName(), src.attr("abs:src"), src.attr("width"), src.attr("height"), trim(src.attr("alt"), 20) ); } else { //输出非<img>多媒体标签 print( " * %s: <%s>", src.tagName(), src.attr("abs:src") ); } } // 显示引用CSS的个数 print("\nImports: (%d)", imports.size()); for (Element link : imports) { // 显示所有引用信息 print(" * %s <%s> (%s)", link.tagName(), link.attr("abs:href"), link.attr("rel")); } // 显示链接的个数 print("\nLinks: (%d)", links.size()); for (Element link : links) { // 显示所有链接信息 print(" * a: <%s> (%s)", link.attr("abs:href"), trim(link.text(), 35)); } } // 自定义输出函数 private static void print(String msg, Object... args) { System.out.println(String.format(msg, args)); } // 截断过长的链接 private static String trim(String s, int width) { if (s.length() > width) return s.substring(0, width-1) + "."; else return s; }}
输出
Fetching http://news.ycombinator.com/...Media: (38)* img: <http://ycombinator.com/images/y18.gif> 18x18 ()* img: <http://ycombinator.com/images/s.gif> 10x1 ()* img: <http://ycombinator.com/images/grayarrow.gif> x ()* img: <http://ycombinator.com/images/s.gif> 0x10 ()* script: <http://www.co2stats.com/propres.php?s=1138>* img: <http://ycombinator.com/images/s.gif> 15x1 ()* img: <http://ycombinator.com/images/hnsearch.png> x ()* img: <http://ycombinator.com/images/s.gif> 25x1 ()* img: <http://mixpanel.com/site_media/images/mixpanel_partner_logo_borderless.gif> x (Analytics by Mixpan.)Imports: (2)* link <http://ycombinator.com/news.css> (stylesheet)* link <http://ycombinator.com/favicon.ico> (shortcut icon)Links: (141)* a: <http://ycombinator.com> ()* a: <http://news.ycombinator.com/news> (Hacker News)* a: <http://news.ycombinator.com/newest> (new)* a: <http://news.ycombinator.com/newcomments> (comments)* a: <http://news.ycombinator.com/leaders> (leaders)* a: <http://news.ycombinator.com/jobs> (jobs)* a: <http://news.ycombinator.com/submit> (submit)* a: <http://news.ycombinator.com/x?fnid=JKhQjfU7gW> (login)* a: <http://news.ycombinator.com/vote?for=1094578&dir=up&whence=%6e%65%77%73> ()* a: <http://www.readwriteweb.com/archives/facebook_gets_faster_debuts_homegrown_php_compiler.php?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+readwriteweb+%28ReadWriteWeb%29&utm_content=Twitter> (Facebook speeds up PHP)* a: <http://news.ycombinator.com/user?id=mcxx> (mcxx)* a: <http://news.ycombinator.com/item?id=1094578> (9 comments)* a: <http://news.ycombinator.com/vote?for=1094649&dir=up&whence=%6e%65%77%73> ()* a: <http://groups.google.com/group/django-developers/msg/a65fbbc8effcd914> ("Tough. Django produces XHTML.")* a: <http://news.ycombinator.com/user?id=andybak> (andybak)* a: <http://news.ycombinator.com/item?id=1094649> (3 comments)* a: <http://news.ycombinator.com/vote?for=1093927&dir=up&whence=%6e%65%77%73> ()* a: <http://news.ycombinator.com/x?fnid=p2sdPLE7Ce> (More)* a: <http://news.ycombinator.com/lists> (Lists)* a: <http://news.ycombinator.com/rss> (RSS)* a: <http://ycombinator.com/bookmarklet.html> (Bookmarklet)* a: <http://ycombinator.com/newsguidelines.html> (Guidelines)* a: <http://ycombinator.com/newsfaq.html> (FAQ)* a: <http://ycombinator.com/newsnews.html> (News News)* a: <http://news.ycombinator.com/item?id=363> (Feature Requests)* a: <http://ycombinator.com> (Y Combinator)* a: <http://ycombinator.com/w2010.html> (Apply)* a: <http://ycombinator.com/lib.html> (Library)* a: <http://www.webmynd.com/html/hackernews.html> ()* a: <http://mixpanel.com/?from=yc> ()
设置属性值
Element.attr(String key, String value)
设置元素某一个属性的值Element.addClass(String className)
为元素添加一个类Element.removeClass(String className)
为元素删除一个类- 批量添加属性:
doc.select("div.comments input").attr("value","someVal");
- 因为
attr
返回修改后的该Element
,所以可以多命令叠加如:doc.select("div.masthead").attr("title", "jsoup").addClass("round-box");
设置HTML
Element.html(String html)
将元素内部的html替换为指定的htmlElement.prepend(String first)
在元素内部的html前面添加新的htmlElement.append(String last)
在元素内部的html结尾添加新的htmlElement.wrap(String arond)
在元素自身html外再包一层新的htmlElement.prependElement(String tag)
在元素内部的开头插入一个新的tagElement.appendElement(String tag)
在元素内部的结尾插入一个新的tag
举例:
// 选择第一个<div>// 假设得到: <div>Hello</div>Element div = doc.select("div").first();// 将第一个div中的html替换为<p>lorem ipsum</p>,得到// <div><p>lorem ipsum</p></div>div.html("<p>lorem ipsum</p>");// 在div的头尾插入新的内容div.prepend("<p>First</p>");div.append("<p>Last</p>");//得到: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div>// 获得第一个<span>// 假设得到: <span>One</span>Element span = doc.select("span").first();// 在span外包裹新的内容span.wrap("<li><a href='http://example.com/'></a></li>");//生成: <li><a href="http://example.com"><span>One</span></a></li>
设置元素文本内容
与Element.html()
最大的不同在于,< >
会被直接转化为文本而不是HTML元素
Element.text(String text)
将元素内部html改变为指定文本Element.prepend(String first)
在元素内部的html之前添加指定文本Element.append(String last)
在元素内部的html之后添加指定文本
举例:
// 选择第一个<div>// 假定获得: <div>Hello</div>Element div = doc.select("div").first();// 替换div中html为文本div.text("five > four"); // 获得: <div>five > four</div>// 在div中首尾添加内容div.prepend("First ");div.append(" Last");// 获得// <div>First five > four Last</div>
防御XSS
XSS = Cross Site Scripting
跨站脚本攻击。大致上跨域攻击和数据库注入攻击(SQL Injection
)都是在提交给服务器的内容中输入了代码。比如XSS攻击可能在表单中输入一段javascript,并在验证不严密的服务器中被存储到了数据库中,下一次用户读取这些数据的时候就会自动调用非法的javascript从而造成信息泄露等。而数据库注入攻击则是在提交的内容
中插入了SQL语句,检查不严的网站接受了这些语句并作为合法SQL的一部分对MYSQL执行,从而可能造成表被删除等后果。
防御XSS的方法:
- 使用加密的session来验证提交表单用户的身份
- 永远不相信客户端发送来的数据,对其进行严格检查
- 一些框架(比如PHP的CodeIgniter)可以使用框架自带的XSS过滤和数据库注入过滤函数
jsoup XSS防御:
使用jsoup.clean()
函数,举例:
String unsafe = "<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";String safe = Jsoup.clean(unsafe, Whitelist.basic());// now: <p><a href="http://example.com/" rel="nofollow">Link</a></p>
参考资料
jsoup官网
http://jsoup.org
jsoup API 列表
http://jsoup.org/apidocs/
bcli 2016-1-21
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 【POJ 1191】 棋盘分割(DP)
- SQL调优 - Hints指定索引 解决慢查询案例
- pat--列出连通集
- OC 中new与alloc/init的区别
- Socket通信模式和URL通信模式
- 欢迎使用CSDN-markdown编辑器
- 银行家算法(1)——概念与举例说明(多进程管理资源分配避免死锁)
- leetcode_065 Valid Number
- SVM-4-核函数
- windows SDK程序的模板
- 使用JsonP进行跨域请求
- Swap Nodes in Pairs
- stm32f103 RTC周期性待机唤醒(一)
- HDU 5646 DZY Loves Partition (数学)