Jsoup解析HTML实例及文档方法详解
解析和遍历一个html文档
如何解析一个html文档:
string html = "<html><head><title>first parse</title></head>"
+ "<body><p>parsed html into a doc.</p></body></html>";
document doc = jsoup.parse(html);
其解析器能够尽最大可能从你提供的html文档来创见一个干净的解析结果,无论html的格式是否完整。比如它可以处理:
1、没有关闭的标签 (比如: <p>lorem <p>ipsum parses to <p>lorem</p> <p>ipsum</p>)
2、隐式标签 (比如. 它可以自动将 <td>table data</td>包装成<table><tr><td>?)
3、创建可靠的文档结构(html标签包含head 和 body,在head只出现恰当的元素)
一个文档的对象模型
1、文档由多个elements和textnodes组成 (以及其它辅助nodes).
2、其继承结构如下:document继承element继承node. textnode继承 node.
3、一个element包含一个子节点集合,并拥有一个父element。他们还提供了一个唯一的子元素过滤列表。
从一个url加载一个document
存在问题
你需要从一个网站获取和解析一个html文档,并查找其中的相关数据。你可以使用下面解决方法:
解决方法
使用 jsoup.connect(string url)方法:
document doc = jsoup.connect("//www.jb51.net/").get();
string title = doc.title();
说明
connect(string url) 方法创建一个新的 connection, 和 get() 取得和解析一个html文件。如果从该url获取html时发生错误,便会抛出 ioexception,应适当处理。
connection 接口还提供一个方法链来解决特殊请求,具体如下:
document doc = jsoup.connect("//www.jb51.net")
.data("query", "java")
.useragent("mozilla")
.cookie("auth", "token")
.timeout(3000)
.post();
这个方法只支持web urls (http和https 协议); 假如你需要从一个文件加载,可以使用parse(file in, string charsetname) 代替。
从一个文件加载一个文档
问题
在本机硬盘上有一个html文件,需要对它进行解析从中抽取数据或进行修改。
办法
可以使用静态 jsoup.parse(file in, string charsetname, string baseuri) 方法:
file input = new file("/tmp/input.html");
document doc = jsoup.parse(input, "utf-8", "//www.jb51.net/");
说明
parse(file in, string charsetname, string baseuri) 这个方法用来加载和解析一个html文件。如在加载文件的时候发生错误,将抛出ioexception,应作适当处理。
baseuri 参数用于解决文件中urls是相对路径的问题。如果不需要可以传入一个空的字符串。
另外还有一个方法parse(file in, string charsetname) ,它使用文件的路径做为 baseuri。 这个方法适用于如果被解析文件位于网站的本地文件系统,且相关链接也指向该文件系统。
使用dom方法来遍历一个文档
问题
你有一个html文档要从中提取数据,并了解这个html文档的结构。
方法
将html解析成一个document之后,就可以使用类似于dom的方法进行操作。示例代码:
file input = new file("/tmp/input.html");
document doc = jsoup.parse(input, "utf-8", "//www.jb51.net/");
element content = doc.getelementbyid("content");
elements links = content.getelementsbytag("a");
for (element link : links) {
string linkhref = link.attr("href");
string linktext = link.text();
}
说明
elements这个对象提供了一系列类似于dom的方法来查找元素,抽取并处理其中的数据。具体如下:
查找元素
getelementbyid(string id)
getelementsbytag(string tag)
getelementsbyclass(string classname)
getelementsbyattribute(string key) (and related methods)
element siblings: siblingelements(), firstelementsibling(), lastelementsibling();nextelementsibling(), previouselementsibling()
graph: parent(), children(), child(int index)
元素数据
attr(string key)获取属性attr(string key, string value)设置属性
attributes()获取所有属性
id(), classname() and classnames()
text()获取文本内容text(string value) 设置文本内容
html()获取元素内htmlhtml(string value)设置元素内的html内容
outerhtml()获取元素外html内容
data()获取数据内容(例如:script和style标签)
tag() and tagname()
操作html和文本
append(string html), prepend(string html)
appendtext(string text), prependtext(string text)
appendelement(string tagname), prependelement(string tagname)
html(string value)
使用选择器语法来查找元素
问题
你想使用类似于css或jquery的语法来查找和操作元素。
方法
可以使用element.select(string selector) 和 elements.select(string selector) 方法实现:
file input = new file("/tmp/input.html");
document doc = jsoup.parse(input, "utf-8", "//www.jb51.net./");
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元素
说明
jsoup elements对象支持类似于css (或jquery)的选择器语法,来实现非常强大和灵活的查找功能。.
这个select 方法在document, element,或elements对象中都可以使用。且是上下文相关的,因此可实现指定元素的过滤,或者链式选择访问。
select方法将返回一个elements集合,并提供一组方法来抽取和处理结果。
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等
可以查看selector api参考来了解更详细的内容
从元素抽取属性,文本和html
问题
在解析获得一个document实例对象,并查找到一些元素之后,你希望取得在这些元素中的数据。
方法
要取得一个属性的值,可以使用node.attr(string key) 方法
对于一个元素中的文本,可以使用element.text()方法
对于要取得元素或属性中的html内容,可以使用element.html(), 或 node.outerhtml()方法
示例:
string html = "<p>an <a href='//www.jb51.net/'><b>www.jb51.net</b></a> link.</p>";
document doc = jsoup.parse(html);//解析html字符串返回一个document实现
element link = doc.select("a").first();//查找第一个a元素
string text = doc.body().text(); // "an www.jb51.net link"//取得字符串中的文本
string linkhref = link.attr("href"); // "//www.jb51.net/"//取得链接地址
string linktext = link.text(); // "www.jb51.net""//取得链接地址中的文本
string linkouterh = link.outerhtml();
// "<a href="//www.jb51.net"><b>www.jb51.net</b></a>"
string linkinnerh = link.html(); // "<b>www.jb51.net</b>"//取得链接内的html内容
说明
上述方法是元素数据访问的核心办法。此外还其它一些方法可以使用:
element.id()
element.tagname()
element.classname() and element.hasclass(string classname)
这些访问器方法都有相应的setter方法来更改数据.
示例程序: 获取所有链接
这个示例程序将展示如何从一个url获得一个页面。然后提取页面中的所有链接、图片和其它辅助内容。并检查urls和文本信息。
运行下面程序需要指定一个urls作为参数
package org.jsoup.www.jb51.nets;
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;
/**
* www.jb51.net program to list links from a url.
*/
public class listlinks {
public static void main(string[] args) throws ioexception {
validate.istrue(args.length == 1, "usage: supply url to fetch");
string url = args[0];
print("fetching %s...", url);
document doc = jsoup.connect(url).get();
elements links = doc.select("a[href]");
elements media = doc.select("[src]");
elements imports = doc.select("link[href]");
print("\nmedia: (%d)", media.size());
for (element src : media) {
if (src.tagname().equals("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
print(" * %s: <%s>", src.tagname(), src.attr("abs:src"));
}
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;
}
}
org/jsoup/www.jb51.nets/listlinks.java
上一篇: JWT.net 操作实践方法