Java的HTML处理神器-jsoup

很久很久以前我还是一个学生的时候,我是使用正则表达式处理HTML标签的,那已经成为一个传说。

后来,使用过 HTML Parser ,但这货使用起来各种Visitor、Filter、Tag会让你抓狂,不愧是Java程序写出来的。

现在,我只使用 jsoup 处理HTML,因为它用起来和jQuery几乎一样,很人道。

加载HTML文档

//直接从字符串加载,而且字符串可以不完整,jsoup会自动填充<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);

//从URL上加载网页
Document doc = Jsoup.connect("http://feichao.org/").get();

//从URL上加载网页,同时设置请求参数
Document doc = Jsoup.connect("http://feichao.org")
  .data("username", "Java")
  .userAgent("Internet Explorer")
  .cookie("remember", "true")
  .timeout(3000)
  .post();

//从本地文件加载
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

查找元素

//获取一个Document对象,这里只是举例
String html = "<html><head><title>First parse</title></head>"
  + "<body><p id=content>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);

//按ID查找
Element content = doc.getElementById("content");
//按标签检索
Elements links = content.getElementsByTag("a"); 
//获得元素集合后,可以直接拿来遍历
for (Element link : links) {
  String linkHref = link.attr("href");
  String linkText = link.text();
}

//使用css选择器查找元素
Elements links = doc.select("a[href]");
Elements pngs = doc.select("img[src$=.png]"); //img的src以png结尾
Element masthead = doc.select("div.masthead").first();
Elements resultLinks = doc.select("h3.r > a");

获取元素数据

String html = "<p>An <a href='/'><b>feichao</b></a> link.</p>";
Document doc = Jsoup.parse(html);
Element link = doc.select("a").first();

String text = doc.body().text(); // "An feichao link"
String linkHref = link.attr("href"); // "/"
String absHref = link.attr("abs:href"); // 获取绝对路径:"http://feichao.org/"
String linkText = link.text(); // "feichao""

String linkOuterH = link.outerHtml(); // "<a href="http://feichao.org"><b>feichao</b></a>"
String linkInnerH = link.html(); // "<b>feichao</b>"

设置元素属性

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://feichao.org/'></a></li>");
// now: <li><a href="http://feichao.org"><span>One</span></a></li>

设置文本

Element div = doc.select("div").first(); // <div></div>
div.text("five > four"); // <div>five &gt; four</div>
div.prepend("First ");
div.append(" Last");

过滤危险字符

很多用户提交的数据,如评论、文章都可能含有一些危险的字符,这些字符轻则导致网页错乱,重则产生用户损失金钱或者隐私。

往常的处理是使用一个丰富的正则表达式来对用户提交的数据进行替换,但这种方式非常累,而且很难完全清除。

jsoup就提供了一个非常好用的功能,直接一句话就将所有危险的字符剔除掉。

String unsafe = 
  "<p><a href='http://feichao.org/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
// now: <p><a href="http://feichao.org/" rel="nofollow">Link</a></p>

jsoup的官网有更加详细的介绍: http://jsoup.org/